diff options
author | Bob Liu <bob.liu@oracle.com> | 2015-12-09 20:16:48 -0500 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2016-01-04 12:21:26 -0500 |
commit | 93bb277f97a6d319361766bde228717faf4abdeb (patch) | |
tree | 6cfb401fa392a96867579ac36bf5eb05826056cb | |
parent | db6fbc106786f26d95889c50c18b1f28aa543a17 (diff) |
xen/blkback: Fix two memory leaks.
This patch fixs two memleaks:
backtrace:
[<ffffffff817ba5e8>] kmemleak_alloc+0x28/0x50
[<ffffffff81205e3b>] kmem_cache_alloc+0xbb/0x1d0
[<ffffffff81534028>] xen_blkbk_probe+0x58/0x230
[<ffffffff8146adb6>] xenbus_dev_probe+0x76/0x130
[<ffffffff81511716>] driver_probe_device+0x166/0x2c0
[<ffffffff815119bc>] __device_attach_driver+0xac/0xb0
[<ffffffff8150fa57>] bus_for_each_drv+0x67/0x90
[<ffffffff81511ab7>] __device_attach+0xc7/0x120
[<ffffffff81511b23>] device_initial_probe+0x13/0x20
[<ffffffff8151059a>] bus_probe_device+0x9a/0xb0
[<ffffffff8150f0a1>] device_add+0x3b1/0x5c0
[<ffffffff8150f47e>] device_register+0x1e/0x30
[<ffffffff8146a9e8>] xenbus_probe_node+0x158/0x170
[<ffffffff8146abaf>] xenbus_dev_changed+0x1af/0x1c0
[<ffffffff8146b1bb>] backend_changed+0x1b/0x20
[<ffffffff81468ca6>] xenwatch_thread+0xb6/0x160
unreferenced object 0xffff880007ba8ef8 (size 224):
backtrace:
[<ffffffff817ba5e8>] kmemleak_alloc+0x28/0x50
[<ffffffff81205c73>] __kmalloc+0xd3/0x1e0
[<ffffffff81534d87>] frontend_changed+0x2c7/0x580
[<ffffffff8146af12>] xenbus_otherend_changed+0xa2/0xb0
[<ffffffff8146b2c0>] frontend_changed+0x10/0x20
[<ffffffff81468ca6>] xenwatch_thread+0xb6/0x160
[<ffffffff810d3e97>] kthread+0xd7/0xf0
[<ffffffff817c4a9f>] ret_from_fork+0x3f/0x70
[<ffffffffffffffff>] 0xffffffffffffffff
unreferenced object 0xffff8800048dcd38 (size 224):
The first leak is caused by not put() the be->blkif reference
which we had gotten in xen_blkif_alloc(), while the second is
us not freeing blkif->rings in the right place.
Signed-off-by: Bob Liu <bob.liu@oracle.com>
Reported-and-Tested-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
-rw-r--r-- | drivers/block/xen-blkback/xenbus.c | 17 |
1 files changed, 11 insertions, 6 deletions
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 44396b8a0cb2..876763f7f13e 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c | |||
@@ -297,8 +297,16 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif) | |||
297 | BUG_ON(ring->free_pages_num != 0); | 297 | BUG_ON(ring->free_pages_num != 0); |
298 | BUG_ON(ring->persistent_gnt_c != 0); | 298 | BUG_ON(ring->persistent_gnt_c != 0); |
299 | WARN_ON(i != (XEN_BLKIF_REQS_PER_PAGE * blkif->nr_ring_pages)); | 299 | WARN_ON(i != (XEN_BLKIF_REQS_PER_PAGE * blkif->nr_ring_pages)); |
300 | xen_blkif_put(blkif); | ||
300 | } | 301 | } |
301 | blkif->nr_ring_pages = 0; | 302 | blkif->nr_ring_pages = 0; |
303 | /* | ||
304 | * blkif->rings was allocated in connect_ring, so we should free it in | ||
305 | * here. | ||
306 | */ | ||
307 | kfree(blkif->rings); | ||
308 | blkif->rings = NULL; | ||
309 | blkif->nr_rings = 0; | ||
302 | 310 | ||
303 | return 0; | 311 | return 0; |
304 | } | 312 | } |
@@ -310,7 +318,6 @@ static void xen_blkif_free(struct xen_blkif *blkif) | |||
310 | xen_vbd_free(&blkif->vbd); | 318 | xen_vbd_free(&blkif->vbd); |
311 | 319 | ||
312 | /* Make sure everything is drained before shutting down */ | 320 | /* Make sure everything is drained before shutting down */ |
313 | kfree(blkif->rings); | ||
314 | kmem_cache_free(xen_blkif_cachep, blkif); | 321 | kmem_cache_free(xen_blkif_cachep, blkif); |
315 | } | 322 | } |
316 | 323 | ||
@@ -484,7 +491,6 @@ static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle, | |||
484 | static int xen_blkbk_remove(struct xenbus_device *dev) | 491 | static int xen_blkbk_remove(struct xenbus_device *dev) |
485 | { | 492 | { |
486 | struct backend_info *be = dev_get_drvdata(&dev->dev); | 493 | struct backend_info *be = dev_get_drvdata(&dev->dev); |
487 | unsigned int i; | ||
488 | 494 | ||
489 | pr_debug("%s %p %d\n", __func__, dev, dev->otherend_id); | 495 | pr_debug("%s %p %d\n", __func__, dev, dev->otherend_id); |
490 | 496 | ||
@@ -499,12 +505,11 @@ static int xen_blkbk_remove(struct xenbus_device *dev) | |||
499 | 505 | ||
500 | dev_set_drvdata(&dev->dev, NULL); | 506 | dev_set_drvdata(&dev->dev, NULL); |
501 | 507 | ||
502 | if (be->blkif) { | 508 | if (be->blkif) |
503 | xen_blkif_disconnect(be->blkif); | 509 | xen_blkif_disconnect(be->blkif); |
504 | for (i = 0; i < be->blkif->nr_rings; i++) | ||
505 | xen_blkif_put(be->blkif); | ||
506 | } | ||
507 | 510 | ||
511 | /* Put the reference we set in xen_blkif_alloc(). */ | ||
512 | xen_blkif_put(be->blkif); | ||
508 | kfree(be->mode); | 513 | kfree(be->mode); |
509 | kfree(be); | 514 | kfree(be); |
510 | return 0; | 515 | return 0; |