virtio_mmio: add cleanup for virtio_mmio_probe
PATCH 1/1 virtio_mmio: add cleanup for virtio_mmio_probe
cleanup all resource allocated by virtio_mmio_probe.
--- drivers/virtio/virtio_mmio.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-)
drivers/virtio/virtio_mmio.c +26 -8
@@ -513,8 +513,10 @@ static int virtio_mmio_probe(struct platform_device *pdev)return -EBUSY ; vm_dev =devm_kzalloc (&pdev->dev,sizeof (*vm_dev),GFP_KERNEL ); -if (!vm_dev) -return -ENOMEM ; +if (!vm_dev) { + rc = -ENOMEM ; + goto free_mem; + } vm_dev->vdev.dev.parent = &pdev->dev; vm_dev->vdev.dev.release = virtio_mmio_release_dev_empty;
@@ -524,14 +526,17 @@ static int virtio_mmio_probe(struct platform_device *pdev)spin_lock_init (&vm_dev->lock); vm_dev->base =devm_ioremap (&pdev->dev, mem->start,resource_size (mem)); -if (vm_dev->base ==NULL ) -return -EFAULT ; +if (vm_dev->base ==NULL ) { + rc = -EFAULT ; + goto free_vmdev; + }/* Check magic value */ magic =readl (vm_dev->base +VIRTIO_MMIO_MAGIC_VALUE );if (magic != ('v' |'i' <<8 |'r' <<16 |'t' <<24 )) {dev_warn (&pdev->dev,"Wrong magic value 0x%08lx!\n" , magic); -return -ENODEV ; + rc = -ENODEV ; + goto unmap; }/* Check device version */
@@ -539,7 +544,8 @@ static int virtio_mmio_probe(struct platform_device *pdev)if (vm_dev->version <1 || vm_dev->version >2 ) {dev_err (&pdev->dev,"Version %ld not supported!\n" , vm_dev->version); -return -ENXIO ; + rc = -ENXIO ; + goto unmap; } vm_dev->vdev.id.device =readl (vm_dev->base +VIRTIO_MMIO_DEVICE_ID );
@@ -548,7 +554,8 @@ static int virtio_mmio_probe(struct platform_device *pdev)* virtio-mmio device with an ID 0 is a (dummy) placeholder * with no function. End probing now with no error reported. */ -return -ENODEV ; + rc = -ENODEV ; + goto unmap; } vm_dev->vdev.id.vendor =readl (vm_dev->base +VIRTIO_MMIO_VENDOR_ID );
@@ -573,7 +580,18 @@ static int virtio_mmio_probe(struct platform_device *pdev)platform_set_drvdata (pdev, vm_dev); -return register_virtio_device (&vm_dev->vdev); + rc =register_virtio_device (&vm_dev->vdev); +if (rc) + goto unmap; +return 0 ; +unmap: +iounmap (vm_dev->base); +free_mem: +devm_release_mem_region (&pdev->dev, mem->start, +resource_size (mem)); +free_vmdev: +devm_kfree (&pdev->dev, vm_dev); +return rc; }static int virtio_mmio_remove (struct platform_device *pdev)
Signature · 1 line
2.9.4
Quoted 12 lines · On Sat, 2 Dec 2017 01:51:40 +0800 weiping zhang <[email protected]> wrote:
cleanup all resource allocated by
virtio_mmio_probe.Signed-off-by weiping zhang <[email protected]>--- drivers/virtio/virtio_mmio.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-)drivers/virtio/virtio_mmio.c +0
-0
drivers/virtio/virtio_mmio.c static int virtio_mmio_probe(struct platform_device *pdev) · line 517
Quoted 7 lines
drivers/virtio/virtio_mmio.c +2
-2@@ -513,8 +513,10 @@ static int virtio_mmio_probe(struct platform_device *pdev)return -EBUSY ; vm_dev =devm_kzalloc (&pdev->dev,sizeof (*vm_dev),GFP_KERNEL ); -if (!vm_dev) -return -ENOMEM ; +if (!vm_dev) { + rc = -ENOMEM ;
Touching this would be a good time to remove the extra space in front of the -ENOMEM :)
Quoted 5 lines
drivers/virtio/virtio_mmio.c +2
-0+ goto free_mem; + } vm_dev->vdev.dev.parent = &pdev->dev; vm_dev->vdev.dev.release = virtio_mmio_release_dev_empty;
(...)
Quoted 6 lines
drivers/virtio/virtio_mmio.c +1
-1@@ -573,7 +580,18 @@ static int virtio_mmio_probe(struct platform_device *pdev)platform_set_drvdata (pdev, vm_dev); -return register_virtio_device (&vm_dev->vdev); + rc =register_virtio_device (&vm_dev->vdev);
drivers/virtio/virtio_mmio.c static int virtio_mmio_probe(struct platform_device *pdev) · line 593
Quoted 10 lines
drivers/virtio/virtio_mmio.c +10
-0+if (rc) + goto unmap; +return 0 ; +unmap: +iounmap (vm_dev->base); +free_mem: +devm_release_mem_region (&pdev->dev, mem->start, +resource_size (mem)); +free_vmdev: +devm_kfree (&pdev->dev, vm_dev);
I think this is problematic as vm_dev embeds a struct device (via embedding a struct virtio_device). I think the right way to do this is
- call this only if register_virtio_device() has not been called
- put the devm_kfree() into the ->release callback for the virtio_device (IOW, replace virtio_mmio_release_dev_empty() with a function that calls this)
- do a put_device() if register_virtio_device() failed
I might be missing some interaction between the usual driver model handling and devm resources, though.
Quoted 4 lines
drivers/virtio/virtio_mmio.c +1
-0+return rc; }static int virtio_mmio_remove (struct platform_device *pdev)
2017-12-04 18:24 GMT+08:00 Cornelia Huck <[email protected]>:
Quoted 17 lines
Quoted 14 lines · On Sat, 2 Dec 2017 01:51:40 +0800 weiping zhang <[email protected]> wrote:
cleanup all resource allocated by
virtio_mmio_probe.Signed-off-by weiping zhang <[email protected]>--- drivers/virtio/virtio_mmio.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-)drivers/virtio/virtio_mmio.c +0
-0@@ -513,8 +513,10 @@ static int virtio_mmio_probe(struct platform_device *pdev)return -EBUSY ;
Quoted 8 lines
drivers/virtio/virtio_mmio.c static int virtio_mmio_probe(struct platform_device *pdev) · line 517
Quoted 5 lines
drivers/virtio/virtio_mmio.c +2
-2vm_dev =devm_kzalloc (&pdev->dev,sizeof (*vm_dev),GFP_KERNEL ); -if (!vm_dev) -return -ENOMEM ; +if (!vm_dev) { + rc = -ENOMEM ;Touching this would be a good time to remove the extra space in front of the
-ENOMEM:)
Thanks, I fix this at V2.
Quoted 34 lines
Quoted 6 lines
drivers/virtio/virtio_mmio.c +2
-0+ goto free_mem; + } vm_dev->vdev.dev.parent = &pdev->dev; vm_dev->vdev.dev.release = virtio_mmio_release_dev_empty;(...)
Quoted 6 lines
drivers/virtio/virtio_mmio.c +1
-1@@ -573,7 +580,18 @@ static int virtio_mmio_probe(struct platform_device *pdev)platform_set_drvdata (pdev, vm_dev); -return register_virtio_device (&vm_dev->vdev); + rc =register_virtio_device (&vm_dev->vdev);drivers/virtio/virtio_mmio.c static int virtio_mmio_probe(struct platform_device *pdev) · line 593
Quoted 10 lines
drivers/virtio/virtio_mmio.c +10
-0+if (rc) + goto unmap; +return 0 ; +unmap: +iounmap (vm_dev->base); +free_mem: +devm_release_mem_region (&pdev->dev, mem->start, +resource_size (mem)); +free_vmdev: +devm_kfree (&pdev->dev, vm_dev);I think this is problematic as
vm_devembeds a struct device (via embedding a structvirtio_device). I think the right way to do this is
- call this only ifregister_virtio_device()has not been called
- put thedevm_kfree()into the ->release callback for thevirtio_device(IOW, replacevirtio_mmio_release_dev_empty()with a function that calls this)
- do aput_device()ifregister_virtio_device()failed
Quoted 3 lines
I might be missing some interaction between the usual driver model handling and devm resources, though.
if fail in virtio_mmio_probe, we need free @mem of @pdev, vdev->base, so I prefer clean all this resource in virtio_mmio_probe itself, keep vdev.dev.release do nothing.
also we need release these resources at virtio_mmio_remove. I'll send V2.
--
thanks a ton