diff options
author | Jens Axboe <axboe@kernel.dk> | 2012-12-01 09:42:41 +0100 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2012-12-01 09:42:41 +0100 |
commit | 84ad6845fbb1248228d3beab8084e4b5f6f82b1d (patch) | |
tree | 43a7e7a4626dcf1957904b49e15c1709e268da44 /drivers | |
parent | 2cecb7309897c872b977a60d53e5de0af4265dd6 (diff) | |
parent | 07c540a0b5f4674538b57ad85bc9306e44fb45dd (diff) |
Merge branch 'stable/for-jens-3.8' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen into for-3.8/drivers
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/block/xen-blkback/blkback.c | 68 | ||||
-rw-r--r-- | drivers/block/xen-blkfront.c | 1 |
2 files changed, 38 insertions, 31 deletions
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index a05961683ef..74374fb762a 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -212,6 +212,39 @@ static struct persistent_gnt *get_persistent_gnt(struct rb_root *root, return NULL; } +static void free_persistent_gnts(struct rb_root *root, unsigned int num) +{ + struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + struct persistent_gnt *persistent_gnt; + int ret = 0; + int segs_to_unmap = 0; + + foreach_grant(persistent_gnt, root, node) { + BUG_ON(persistent_gnt->handle == + BLKBACK_INVALID_HANDLE); + gnttab_set_unmap_op(&unmap[segs_to_unmap], + (unsigned long) pfn_to_kaddr(page_to_pfn( + persistent_gnt->page)), + GNTMAP_host_map, + persistent_gnt->handle); + + pages[segs_to_unmap] = persistent_gnt->page; + rb_erase(&persistent_gnt->node, root); + kfree(persistent_gnt); + num--; + + if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST || + !rb_next(&persistent_gnt->node)) { + ret = gnttab_unmap_refs(unmap, NULL, pages, + segs_to_unmap); + BUG_ON(ret); + segs_to_unmap = 0; + } + } + BUG_ON(num != 0); +} + /* * Retrieve from the 'pending_reqs' a free pending_req structure to be used. */ @@ -358,11 +391,6 @@ int xen_blkif_schedule(void *arg) { struct xen_blkif *blkif = arg; struct xen_vbd *vbd = &blkif->vbd; - struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST]; - struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST]; - struct persistent_gnt *persistent_gnt; - int ret = 0; - int segs_to_unmap = 0; xen_blkif_get(blkif); @@ -391,34 +419,12 @@ int xen_blkif_schedule(void *arg) } /* Free all persistent grant pages */ - if (!RB_EMPTY_ROOT(&blkif->persistent_gnts)) { - foreach_grant(persistent_gnt, &blkif->persistent_gnts, node) { - BUG_ON(persistent_gnt->handle == - BLKBACK_INVALID_HANDLE); - gnttab_set_unmap_op(&unmap[segs_to_unmap], - (unsigned long) pfn_to_kaddr(page_to_pfn( - persistent_gnt->page)), - GNTMAP_host_map, - persistent_gnt->handle); - - pages[segs_to_unmap] = persistent_gnt->page; - rb_erase(&persistent_gnt->node, - &blkif->persistent_gnts); - kfree(persistent_gnt); - blkif->persistent_gnt_c--; - - if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST || - !rb_next(&persistent_gnt->node)) { - ret = gnttab_unmap_refs(unmap, NULL, pages, - segs_to_unmap); - BUG_ON(ret); - segs_to_unmap = 0; - } - } - } + if (!RB_EMPTY_ROOT(&blkif->persistent_gnts)) + free_persistent_gnts(&blkif->persistent_gnts, + blkif->persistent_gnt_c); - BUG_ON(blkif->persistent_gnt_c != 0); BUG_ON(!RB_EMPTY_ROOT(&blkif->persistent_gnts)); + blkif->persistent_gnt_c = 0; if (log_stats) print_stats(blkif); diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index f1de806b0a6..96e9b00db08 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -806,6 +806,7 @@ static void blkif_free(struct blkfront_info *info, int suspend) all_gnts = llist_del_all(&info->persistent_gnts); llist_for_each_entry(persistent_gnt, all_gnts, node) { gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL); + __free_page(pfn_to_page(persistent_gnt->pfn)); kfree(persistent_gnt); } info->persistent_gnts_c = 0; |