aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/block/xen-blkback/blkback.c169
-rw-r--r--drivers/block/xen-blkback/common.h3
2 files changed, 122 insertions, 50 deletions
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index 908e630240bd..2a04d341e598 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -47,6 +47,7 @@
47#include <asm/xen/hypervisor.h> 47#include <asm/xen/hypervisor.h>
48#include <asm/xen/hypercall.h> 48#include <asm/xen/hypercall.h>
49#include <xen/balloon.h> 49#include <xen/balloon.h>
50#include <xen/grant_table.h>
50#include "common.h" 51#include "common.h"
51 52
52/* 53/*
@@ -262,6 +263,17 @@ static void put_persistent_gnt(struct xen_blkif *blkif,
262 atomic_dec(&blkif->persistent_gnt_in_use); 263 atomic_dec(&blkif->persistent_gnt_in_use);
263} 264}
264 265
266static void free_persistent_gnts_unmap_callback(int result,
267 struct gntab_unmap_queue_data *data)
268{
269 struct completion *c = data->data;
270
271 /* BUG_ON used to reproduce existing behaviour,
272 but is this the best way to deal with this? */
273 BUG_ON(result);
274 complete(c);
275}
276
265static void free_persistent_gnts(struct xen_blkif *blkif, struct rb_root *root, 277static void free_persistent_gnts(struct xen_blkif *blkif, struct rb_root *root,
266 unsigned int num) 278 unsigned int num)
267{ 279{
@@ -269,8 +281,17 @@ static void free_persistent_gnts(struct xen_blkif *blkif, struct rb_root *root,
269 struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST]; 281 struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];
270 struct persistent_gnt *persistent_gnt; 282 struct persistent_gnt *persistent_gnt;
271 struct rb_node *n; 283 struct rb_node *n;
272 int ret = 0;
273 int segs_to_unmap = 0; 284 int segs_to_unmap = 0;
285 struct gntab_unmap_queue_data unmap_data;
286 struct completion unmap_completion;
287
288 init_completion(&unmap_completion);
289
290 unmap_data.data = &unmap_completion;
291 unmap_data.done = &free_persistent_gnts_unmap_callback;
292 unmap_data.pages = pages;
293 unmap_data.unmap_ops = unmap;
294 unmap_data.kunmap_ops = NULL;
274 295
275 foreach_grant_safe(persistent_gnt, n, root, node) { 296 foreach_grant_safe(persistent_gnt, n, root, node) {
276 BUG_ON(persistent_gnt->handle == 297 BUG_ON(persistent_gnt->handle ==
@@ -285,9 +306,11 @@ static void free_persistent_gnts(struct xen_blkif *blkif, struct rb_root *root,
285 306
286 if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST || 307 if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST ||
287 !rb_next(&persistent_gnt->node)) { 308 !rb_next(&persistent_gnt->node)) {
288 ret = gnttab_unmap_refs(unmap, NULL, pages, 309
289 segs_to_unmap); 310 unmap_data.count = segs_to_unmap;
290 BUG_ON(ret); 311 gnttab_unmap_refs_async(&unmap_data);
312 wait_for_completion(&unmap_completion);
313
291 put_free_pages(blkif, pages, segs_to_unmap); 314 put_free_pages(blkif, pages, segs_to_unmap);
292 segs_to_unmap = 0; 315 segs_to_unmap = 0;
293 } 316 }
@@ -653,18 +676,14 @@ void xen_blkbk_free_caches(struct xen_blkif *blkif)
653 shrink_free_pagepool(blkif, 0 /* All */); 676 shrink_free_pagepool(blkif, 0 /* All */);
654} 677}
655 678
656/* 679static unsigned int xen_blkbk_unmap_prepare(
657 * Unmap the grant references, and also remove the M2P over-rides 680 struct xen_blkif *blkif,
658 * used in the 'pending_req'. 681 struct grant_page **pages,
659 */ 682 unsigned int num,
660static void xen_blkbk_unmap(struct xen_blkif *blkif, 683 struct gnttab_unmap_grant_ref *unmap_ops,
661 struct grant_page *pages[], 684 struct page **unmap_pages)
662 int num)
663{ 685{
664 struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
665 struct page *unmap_pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];
666 unsigned int i, invcount = 0; 686 unsigned int i, invcount = 0;
667 int ret;
668 687
669 for (i = 0; i < num; i++) { 688 for (i = 0; i < num; i++) {
670 if (pages[i]->persistent_gnt != NULL) { 689 if (pages[i]->persistent_gnt != NULL) {
@@ -674,21 +693,95 @@ static void xen_blkbk_unmap(struct xen_blkif *blkif,
674 if (pages[i]->handle == BLKBACK_INVALID_HANDLE) 693 if (pages[i]->handle == BLKBACK_INVALID_HANDLE)
675 continue; 694 continue;
676 unmap_pages[invcount] = pages[i]->page; 695 unmap_pages[invcount] = pages[i]->page;
677 gnttab_set_unmap_op(&unmap[invcount], vaddr(pages[i]->page), 696 gnttab_set_unmap_op(&unmap_ops[invcount], vaddr(pages[i]->page),
678 GNTMAP_host_map, pages[i]->handle); 697 GNTMAP_host_map, pages[i]->handle);
679 pages[i]->handle = BLKBACK_INVALID_HANDLE; 698 pages[i]->handle = BLKBACK_INVALID_HANDLE;
680 if (++invcount == BLKIF_MAX_SEGMENTS_PER_REQUEST) { 699 invcount++;
681 ret = gnttab_unmap_refs(unmap, NULL, unmap_pages, 700 }
682 invcount); 701
702 return invcount;
703}
704
705static void xen_blkbk_unmap_and_respond_callback(int result, struct gntab_unmap_queue_data *data)
706{
707 struct pending_req* pending_req = (struct pending_req*) (data->data);
708 struct xen_blkif *blkif = pending_req->blkif;
709
710 /* BUG_ON used to reproduce existing behaviour,
711 but is this the best way to deal with this? */
712 BUG_ON(result);
713
714 put_free_pages(blkif, data->pages, data->count);
715 make_response(blkif, pending_req->id,
716 pending_req->operation, pending_req->status);
717 free_req(blkif, pending_req);
718 /*
719 * Make sure the request is freed before releasing blkif,
720 * or there could be a race between free_req and the
721 * cleanup done in xen_blkif_free during shutdown.
722 *
723 * NB: The fact that we might try to wake up pending_free_wq
724 * before drain_complete (in case there's a drain going on)
725 * it's not a problem with our current implementation
726 * because we can assure there's no thread waiting on
727 * pending_free_wq if there's a drain going on, but it has
728 * to be taken into account if the current model is changed.
729 */
730 if (atomic_dec_and_test(&blkif->inflight) && atomic_read(&blkif->drain)) {
731 complete(&blkif->drain_complete);
732 }
733 xen_blkif_put(blkif);
734}
735
736static void xen_blkbk_unmap_and_respond(struct pending_req *req)
737{
738 struct gntab_unmap_queue_data* work = &req->gnttab_unmap_data;
739 struct xen_blkif *blkif = req->blkif;
740 struct grant_page **pages = req->segments;
741 unsigned int invcount;
742
743 invcount = xen_blkbk_unmap_prepare(blkif, pages, req->nr_pages,
744 req->unmap, req->unmap_pages);
745
746 work->data = req;
747 work->done = xen_blkbk_unmap_and_respond_callback;
748 work->unmap_ops = req->unmap;
749 work->kunmap_ops = NULL;
750 work->pages = req->unmap_pages;
751 work->count = invcount;
752
753 gnttab_unmap_refs_async(&req->gnttab_unmap_data);
754}
755
756
757/*
758 * Unmap the grant references.
759 *
760 * This could accumulate ops up to the batch size to reduce the number
761 * of hypercalls, but since this is only used in error paths there's
762 * no real need.
763 */
764static void xen_blkbk_unmap(struct xen_blkif *blkif,
765 struct grant_page *pages[],
766 int num)
767{
768 struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
769 struct page *unmap_pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];
770 unsigned int invcount = 0;
771 int ret;
772
773 while (num) {
774 unsigned int batch = min(num, BLKIF_MAX_SEGMENTS_PER_REQUEST);
775
776 invcount = xen_blkbk_unmap_prepare(blkif, pages, batch,
777 unmap, unmap_pages);
778 if (invcount) {
779 ret = gnttab_unmap_refs(unmap, NULL, unmap_pages, invcount);
683 BUG_ON(ret); 780 BUG_ON(ret);
684 put_free_pages(blkif, unmap_pages, invcount); 781 put_free_pages(blkif, unmap_pages, invcount);
685 invcount = 0;
686 } 782 }
687 } 783 pages += batch;
688 if (invcount) { 784 num -= batch;
689 ret = gnttab_unmap_refs(unmap, NULL, unmap_pages, invcount);
690 BUG_ON(ret);
691 put_free_pages(blkif, unmap_pages, invcount);
692 } 785 }
693} 786}
694 787
@@ -982,32 +1075,8 @@ static void __end_block_io_op(struct pending_req *pending_req, int error)
982 * the grant references associated with 'request' and provide 1075 * the grant references associated with 'request' and provide
983 * the proper response on the ring. 1076 * the proper response on the ring.
984 */ 1077 */
985 if (atomic_dec_and_test(&pending_req->pendcnt)) { 1078 if (atomic_dec_and_test(&pending_req->pendcnt))
986 struct xen_blkif *blkif = pending_req->blkif; 1079 xen_blkbk_unmap_and_respond(pending_req);
987
988 xen_blkbk_unmap(blkif,
989 pending_req->segments,
990 pending_req->nr_pages);
991 make_response(blkif, pending_req->id,
992 pending_req->operation, pending_req->status);
993 free_req(blkif, pending_req);
994 /*
995 * Make sure the request is freed before releasing blkif,
996 * or there could be a race between free_req and the
997 * cleanup done in xen_blkif_free during shutdown.
998 *
999 * NB: The fact that we might try to wake up pending_free_wq
1000 * before drain_complete (in case there's a drain going on)
1001 * it's not a problem with our current implementation
1002 * because we can assure there's no thread waiting on
1003 * pending_free_wq if there's a drain going on, but it has
1004 * to be taken into account if the current model is changed.
1005 */
1006 if (atomic_dec_and_test(&blkif->inflight) && atomic_read(&blkif->drain)) {
1007 complete(&blkif->drain_complete);
1008 }
1009 xen_blkif_put(blkif);
1010 }
1011} 1080}
1012 1081
1013/* 1082/*
diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h
index f65b807e3236..cc90a840e616 100644
--- a/drivers/block/xen-blkback/common.h
+++ b/drivers/block/xen-blkback/common.h
@@ -350,6 +350,9 @@ struct pending_req {
350 struct grant_page *indirect_pages[MAX_INDIRECT_PAGES]; 350 struct grant_page *indirect_pages[MAX_INDIRECT_PAGES];
351 struct seg_buf seg[MAX_INDIRECT_SEGMENTS]; 351 struct seg_buf seg[MAX_INDIRECT_SEGMENTS];
352 struct bio *biolist[MAX_INDIRECT_SEGMENTS]; 352 struct bio *biolist[MAX_INDIRECT_SEGMENTS];
353 struct gnttab_unmap_grant_ref unmap[MAX_INDIRECT_SEGMENTS];
354 struct page *unmap_pages[MAX_INDIRECT_SEGMENTS];
355 struct gntab_unmap_queue_data gnttab_unmap_data;
353}; 356};
354 357
355 358