aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorBob Liu <bob.liu@oracle.com>2015-04-03 02:42:58 -0400
committerDavid Vrabel <david.vrabel@citrix.com>2015-04-27 06:40:10 -0400
commit325d73bf8fea8af2227240b7305253fb052d3a68 (patch)
tree668f710fb14540c3ac44fc9dbd83059a8acd1976 /drivers/block
parentb787f68c36d49bb1d9236f403813641efa74a031 (diff)
xen/blkback: safely unmap purge persistent grants
Commit c43cf3ea8385 ("xen-blkback: safely unmap grants in case they are still in use") use gnttab_unmap_refs_async() to wait until the mapped pages are no longer in use before unmapping them, but that commit missed the persistent case. Purge persistent pages can't be unmapped either unless no longer in use. Signed-off-by: Bob Liu <bob.liu@oracle.com> Acked-by: Roger Pau Monné <roger.pau@citrix.com> Signed-off-by: David Vrabel <david.vrabel@citrix.com>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/xen-blkback/blkback.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index bd2b3bbbb22c..48e98f2712b5 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -329,8 +329,18 @@ void xen_blkbk_unmap_purged_grants(struct work_struct *work)
329 struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST]; 329 struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
330 struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST]; 330 struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];
331 struct persistent_gnt *persistent_gnt; 331 struct persistent_gnt *persistent_gnt;
332 int ret, segs_to_unmap = 0; 332 int segs_to_unmap = 0;
333 struct xen_blkif *blkif = container_of(work, typeof(*blkif), persistent_purge_work); 333 struct xen_blkif *blkif = container_of(work, typeof(*blkif), persistent_purge_work);
334 struct gntab_unmap_queue_data unmap_data;
335 struct completion unmap_completion;
336
337 init_completion(&unmap_completion);
338
339 unmap_data.data = &unmap_completion;
340 unmap_data.done = &free_persistent_gnts_unmap_callback;
341 unmap_data.pages = pages;
342 unmap_data.unmap_ops = unmap;
343 unmap_data.kunmap_ops = NULL;
334 344
335 while(!list_empty(&blkif->persistent_purge_list)) { 345 while(!list_empty(&blkif->persistent_purge_list)) {
336 persistent_gnt = list_first_entry(&blkif->persistent_purge_list, 346 persistent_gnt = list_first_entry(&blkif->persistent_purge_list,
@@ -346,17 +356,19 @@ void xen_blkbk_unmap_purged_grants(struct work_struct *work)
346 pages[segs_to_unmap] = persistent_gnt->page; 356 pages[segs_to_unmap] = persistent_gnt->page;
347 357
348 if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST) { 358 if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST) {
349 ret = gnttab_unmap_refs(unmap, NULL, pages, 359 unmap_data.count = segs_to_unmap;
350 segs_to_unmap); 360 gnttab_unmap_refs_async(&unmap_data);
351 BUG_ON(ret); 361 wait_for_completion(&unmap_completion);
362
352 put_free_pages(blkif, pages, segs_to_unmap); 363 put_free_pages(blkif, pages, segs_to_unmap);
353 segs_to_unmap = 0; 364 segs_to_unmap = 0;
354 } 365 }
355 kfree(persistent_gnt); 366 kfree(persistent_gnt);
356 } 367 }
357 if (segs_to_unmap > 0) { 368 if (segs_to_unmap > 0) {
358 ret = gnttab_unmap_refs(unmap, NULL, pages, segs_to_unmap); 369 unmap_data.count = segs_to_unmap;
359 BUG_ON(ret); 370 gnttab_unmap_refs_async(&unmap_data);
371 wait_for_completion(&unmap_completion);
360 put_free_pages(blkif, pages, segs_to_unmap); 372 put_free_pages(blkif, pages, segs_to_unmap);
361 } 373 }
362} 374}