aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/xen-blkback
diff options
context:
space:
mode:
authorRoger Pau Monne <roger.pau@citrix.com>2015-09-04 06:08:07 -0400
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2015-09-23 12:09:19 -0400
commitf929d42ceb18a8acfd47e0e7b7d90b5d49bd9258 (patch)
tree753d7ef59a86092f9cc5a3abe65faf61a4a3a425 /drivers/block/xen-blkback
parente19b127f5b76ec03b9c52b64f117dc75bb39eda1 (diff)
xen/blkback: free requests on disconnection
This is due to commit 86839c56dee28c315a4c19b7bfee450ccd84cd25 "xen/block: add multi-page ring support" When using an guest under UEFI - after the domain is destroyed the following warning comes from blkback. ------------[ cut here ]------------ WARNING: CPU: 2 PID: 95 at /home/julien/works/linux/drivers/block/xen-blkback/xenbus.c:274 xen_blkif_deferred_free+0x1f4/0x1f8() Modules linked in: CPU: 2 PID: 95 Comm: kworker/2:1 Tainted: G W 4.2.0 #85 Hardware name: APM X-Gene Mustang board (DT) Workqueue: events xen_blkif_deferred_free Call trace: [<ffff8000000890a8>] dump_backtrace+0x0/0x124 [<ffff8000000891dc>] show_stack+0x10/0x1c [<ffff8000007653bc>] dump_stack+0x78/0x98 [<ffff800000097e88>] warn_slowpath_common+0x9c/0xd4 [<ffff800000097f80>] warn_slowpath_null+0x14/0x20 [<ffff800000557a0c>] xen_blkif_deferred_free+0x1f0/0x1f8 [<ffff8000000ad020>] process_one_work+0x160/0x3b4 [<ffff8000000ad3b4>] worker_thread+0x140/0x494 [<ffff8000000b2e34>] kthread+0xd8/0xf0 ---[ end trace 6f859b7883c88cdd ]--- Request allocation has been moved to connect_ring, which is called every time blkback connects to the frontend (this can happen multiple times during a blkback instance life cycle). On the other hand, request freeing has not been moved, so it's only called when destroying the backend instance. Due to this mismatch, blkback can allocate the request pool multiple times, without freeing it. In order to fix it, move the freeing of requests to xen_blkif_disconnect to restore the symmetry between request allocation and freeing. Reported-by: Julien Grall <julien.grall@citrix.com> Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> Tested-by: Julien Grall <julien.grall@citrix.com> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com> Cc: David Vrabel <david.vrabel@citrix.com> Cc: xen-devel@lists.xenproject.org CC: stable@vger.kernel.org # 4.2 Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers/block/xen-blkback')
-rw-r--r--drivers/block/xen-blkback/xenbus.c38
1 files changed, 20 insertions, 18 deletions
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
index deb3f001791f..767657565de6 100644
--- a/drivers/block/xen-blkback/xenbus.c
+++ b/drivers/block/xen-blkback/xenbus.c
@@ -212,6 +212,9 @@ static int xen_blkif_map(struct xen_blkif *blkif, grant_ref_t *gref,
212 212
213static int xen_blkif_disconnect(struct xen_blkif *blkif) 213static int xen_blkif_disconnect(struct xen_blkif *blkif)
214{ 214{
215 struct pending_req *req, *n;
216 int i = 0, j;
217
215 if (blkif->xenblkd) { 218 if (blkif->xenblkd) {
216 kthread_stop(blkif->xenblkd); 219 kthread_stop(blkif->xenblkd);
217 wake_up(&blkif->shutdown_wq); 220 wake_up(&blkif->shutdown_wq);
@@ -238,13 +241,28 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)
238 /* Remove all persistent grants and the cache of ballooned pages. */ 241 /* Remove all persistent grants and the cache of ballooned pages. */
239 xen_blkbk_free_caches(blkif); 242 xen_blkbk_free_caches(blkif);
240 243
244 /* Check that there is no request in use */
245 list_for_each_entry_safe(req, n, &blkif->pending_free, free_list) {
246 list_del(&req->free_list);
247
248 for (j = 0; j < MAX_INDIRECT_SEGMENTS; j++)
249 kfree(req->segments[j]);
250
251 for (j = 0; j < MAX_INDIRECT_PAGES; j++)
252 kfree(req->indirect_pages[j]);
253
254 kfree(req);
255 i++;
256 }
257
258 WARN_ON(i != (XEN_BLKIF_REQS_PER_PAGE * blkif->nr_ring_pages));
259 blkif->nr_ring_pages = 0;
260
241 return 0; 261 return 0;
242} 262}
243 263
244static void xen_blkif_free(struct xen_blkif *blkif) 264static void xen_blkif_free(struct xen_blkif *blkif)
245{ 265{
246 struct pending_req *req, *n;
247 int i = 0, j;
248 266
249 xen_blkif_disconnect(blkif); 267 xen_blkif_disconnect(blkif);
250 xen_vbd_free(&blkif->vbd); 268 xen_vbd_free(&blkif->vbd);
@@ -257,22 +275,6 @@ static void xen_blkif_free(struct xen_blkif *blkif)
257 BUG_ON(!list_empty(&blkif->free_pages)); 275 BUG_ON(!list_empty(&blkif->free_pages));
258 BUG_ON(!RB_EMPTY_ROOT(&blkif->persistent_gnts)); 276 BUG_ON(!RB_EMPTY_ROOT(&blkif->persistent_gnts));
259 277
260 /* Check that there is no request in use */
261 list_for_each_entry_safe(req, n, &blkif->pending_free, free_list) {
262 list_del(&req->free_list);
263
264 for (j = 0; j < MAX_INDIRECT_SEGMENTS; j++)
265 kfree(req->segments[j]);
266
267 for (j = 0; j < MAX_INDIRECT_PAGES; j++)
268 kfree(req->indirect_pages[j]);
269
270 kfree(req);
271 i++;
272 }
273
274 WARN_ON(i != (XEN_BLKIF_REQS_PER_PAGE * blkif->nr_ring_pages));
275
276 kmem_cache_free(xen_blkif_cachep, blkif); 278 kmem_cache_free(xen_blkif_cachep, blkif);
277} 279}
278 280