From d1c856e0f1a4c946c6329cff126548ef4288735f Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 19 Nov 2007 11:20:40 -0500 Subject: [PATCH 1/4] lguest: Fix uninitialized members in example launcher Thanks valgrind! Signed-off-by: Rusty Russell --- Documentation/lguest/lguest.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c index 42008395534d..9b0e322118b5 100644 --- a/Documentation/lguest/lguest.c +++ b/Documentation/lguest/lguest.c @@ -1040,6 +1040,11 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs, / getpagesize(); p = get_pages(pages); + /* Initialize the virtqueue */ + vq->next = NULL; + vq->last_avail_idx = 0; + vq->dev = dev; + /* Initialize the configuration. */ vq->config.num = num_descs; vq->config.irq = devices.next_irq++; @@ -1057,9 +1062,6 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs, for (i = &dev->vq; *i; i = &(*i)->next); *i = vq; - /* Link virtqueue back to device. */ - vq->dev = dev; - /* Set the routine to call when the Guest does something to this * virtqueue. */ vq->handle_output = handle_output; @@ -1093,6 +1095,7 @@ static struct device *new_device(const char *name, u16 type, int fd, dev->desc = new_dev_desc(type); dev->handle_input = handle_input; dev->name = name; + dev->vq = NULL; return dev; } From 74b2553f1d13e60fb27063204bd5b6908a6f8494 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 19 Nov 2007 11:20:42 -0500 Subject: [PATCH 2/4] virtio: fix module/device unloading The virtio code never hooked through the ->remove callback. Although noone supports device removal at the moment, this code is already needed for module unloading. This of course also revealed bugs in virtio_blk, virtio_net and lguest unloading paths. Signed-off-by: Rusty Russell --- drivers/block/virtio_blk.c | 10 +++++++--- drivers/lguest/lguest_device.c | 2 ++ drivers/net/virtio_net.c | 8 ++++++-- drivers/virtio/virtio.c | 13 +++++++++++++ 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 3cf7129d83e6..924ddd8bccd2 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -223,7 +223,7 @@ static int virtblk_probe(struct virtio_device *vdev) err = virtio_config_val(vdev, VIRTIO_CONFIG_BLK_F_CAPACITY, &cap); if (err) { dev_err(&vdev->dev, "Bad/missing capacity in config\n"); - goto out_put_disk; + goto out_cleanup_queue; } /* If capacity is too big, truncate with warning. */ @@ -239,7 +239,7 @@ static int virtblk_probe(struct virtio_device *vdev) blk_queue_max_segment_size(vblk->disk->queue, v); else if (err != -ENOENT) { dev_err(&vdev->dev, "Bad SIZE_MAX in config\n"); - goto out_put_disk; + goto out_cleanup_queue; } err = virtio_config_val(vdev, VIRTIO_CONFIG_BLK_F_SEG_MAX, &v); @@ -247,12 +247,14 @@ static int virtblk_probe(struct virtio_device *vdev) blk_queue_max_hw_segments(vblk->disk->queue, v); else if (err != -ENOENT) { dev_err(&vdev->dev, "Bad SEG_MAX in config\n"); - goto out_put_disk; + goto out_cleanup_queue; } add_disk(vblk->disk); return 0; +out_cleanup_queue: + blk_cleanup_queue(vblk->disk->queue); out_put_disk: put_disk(vblk->disk); out_unregister_blkdev: @@ -277,6 +279,8 @@ static void virtblk_remove(struct virtio_device *vdev) put_disk(vblk->disk); unregister_blkdev(major, "virtblk"); mempool_destroy(vblk->pool); + /* There should be nothing in the queue now, so no need to shutdown */ + vdev->config->del_vq(vblk->vq); kfree(vblk); } diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index 66f38722253a..e2eec38c83c2 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c @@ -247,6 +247,8 @@ static void lg_del_vq(struct virtqueue *vq) { struct lguest_vq_info *lvq = vq->priv; + /* Release the interrupt */ + free_irq(lvq->config.irq, vq); /* Tell virtio_ring.c to free the virtqueue. */ vring_del_virtqueue(vq); /* Unmap the pages containing the ring. */ diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index a75be57fb209..d74e6f4aa248 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -404,8 +404,12 @@ free: static void virtnet_remove(struct virtio_device *vdev) { - unregister_netdev(vdev->priv); - free_netdev(vdev->priv); + struct virtnet_info *vi = vdev->priv; + + vdev->config->del_vq(vi->svq); + vdev->config->del_vq(vi->rvq); + unregister_netdev(vi->dev); + free_netdev(vi->dev); } static struct virtio_device_id id_table[] = { diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 15d7787dea87..69d7ea02cd48 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -96,10 +96,23 @@ static int virtio_dev_probe(struct device *_d) return err; } +static int virtio_dev_remove(struct device *_d) +{ + struct virtio_device *dev = container_of(_d,struct virtio_device,dev); + struct virtio_driver *drv = container_of(dev->dev.driver, + struct virtio_driver, driver); + + dev->config->set_status(dev, dev->config->get_status(dev) + & ~VIRTIO_CONFIG_S_DRIVER); + drv->remove(dev); + return 0; +} + int register_virtio_driver(struct virtio_driver *driver) { driver->driver.bus = &virtio_bus; driver->driver.probe = virtio_dev_probe; + driver->driver.remove = virtio_dev_remove; return driver_register(&driver->driver); } EXPORT_SYMBOL_GPL(register_virtio_driver); From 9a4b9708f1f2eaf5edd619df578cf3afec36eb82 Mon Sep 17 00:00:00 2001 From: Matti Linnanvuori Date: Thu, 8 Nov 2007 08:37:38 -0800 Subject: [PATCH 3/4] module: fix and elaborate comments Fix and elaborate comments. Signed-off-by: Matti Linnanvuori Signed-off-by: Rusty Russell --- kernel/module.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/kernel/module.c b/kernel/module.c index 3202c9950073..91fe6958b6e1 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -81,7 +81,8 @@ int unregister_module_notifier(struct notifier_block * nb) } EXPORT_SYMBOL(unregister_module_notifier); -/* We require a truly strong try_module_get() */ +/* We require a truly strong try_module_get(): 0 means failure due to + ongoing or failed initialization etc. */ static inline int strong_try_module_get(struct module *mod) { if (mod && mod->state == MODULE_STATE_COMING) @@ -952,7 +953,8 @@ static unsigned long resolve_symbol(Elf_Shdr *sechdrs, ret = __find_symbol(name, &owner, &crc, !(mod->taints & TAINT_PROPRIETARY_MODULE)); if (ret) { - /* use_module can fail due to OOM, or module unloading */ + /* use_module can fail due to OOM, + or module initialization or unloading */ if (!check_version(sechdrs, versindex, name, mod, crc) || !use_module(mod, owner)) ret = 0; @@ -1369,7 +1371,7 @@ dup: return ret; } -/* Change all symbols so that sh_value encodes the pointer directly. */ +/* Change all symbols so that st_value encodes the pointer directly. */ static int simplify_symbols(Elf_Shdr *sechdrs, unsigned int symindex, const char *strtab, From 8329d98e480250ef5f5a083f9c3af50510b5e65d Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 19 Nov 2007 11:20:43 -0500 Subject: [PATCH 4/4] virtio: fix net driver loop case where we fail to restart skb is only NULL the first time around: it's more correct to test for being under-budget. Signed-off-by: Rusty Russell --- drivers/net/virtio_net.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index d74e6f4aa248..5413dbf3d4ac 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -198,8 +198,8 @@ again: if (vi->num < vi->max / 2) try_fill_recv(vi); - /* All done? */ - if (!skb) { + /* Out of packets? */ + if (received < budget) { netif_rx_complete(vi->dev, napi); if (unlikely(!vi->rvq->vq_ops->restart(vi->rvq)) && netif_rx_reschedule(vi->dev, napi))