diff options
-rw-r--r-- | drivers/block/xen-blkback/blkback.c | 27 | ||||
-rw-r--r-- | drivers/block/xen-blkback/common.h | 1 | ||||
-rw-r--r-- | drivers/block/xen-blkback/xenbus.c | 12 |
3 files changed, 31 insertions, 9 deletions
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 30ef7b390df5..dcfe49fd3cb4 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c | |||
@@ -375,7 +375,7 @@ static void purge_persistent_gnt(struct xen_blkif *blkif) | |||
375 | 375 | ||
376 | pr_debug(DRV_PFX "Going to purge %u persistent grants\n", num_clean); | 376 | pr_debug(DRV_PFX "Going to purge %u persistent grants\n", num_clean); |
377 | 377 | ||
378 | INIT_LIST_HEAD(&blkif->persistent_purge_list); | 378 | BUG_ON(!list_empty(&blkif->persistent_purge_list)); |
379 | root = &blkif->persistent_gnts; | 379 | root = &blkif->persistent_gnts; |
380 | purge_list: | 380 | purge_list: |
381 | foreach_grant_safe(persistent_gnt, n, root, node) { | 381 | foreach_grant_safe(persistent_gnt, n, root, node) { |
@@ -625,6 +625,23 @@ purge_gnt_list: | |||
625 | print_stats(blkif); | 625 | print_stats(blkif); |
626 | } | 626 | } |
627 | 627 | ||
628 | /* Drain pending purge work */ | ||
629 | flush_work(&blkif->persistent_purge_work); | ||
630 | |||
631 | if (log_stats) | ||
632 | print_stats(blkif); | ||
633 | |||
634 | blkif->xenblkd = NULL; | ||
635 | xen_blkif_put(blkif); | ||
636 | |||
637 | return 0; | ||
638 | } | ||
639 | |||
640 | /* | ||
641 | * Remove persistent grants and empty the pool of free pages | ||
642 | */ | ||
643 | void xen_blkbk_free_caches(struct xen_blkif *blkif) | ||
644 | { | ||
628 | /* Free all persistent grant pages */ | 645 | /* Free all persistent grant pages */ |
629 | if (!RB_EMPTY_ROOT(&blkif->persistent_gnts)) | 646 | if (!RB_EMPTY_ROOT(&blkif->persistent_gnts)) |
630 | free_persistent_gnts(blkif, &blkif->persistent_gnts, | 647 | free_persistent_gnts(blkif, &blkif->persistent_gnts, |
@@ -635,14 +652,6 @@ purge_gnt_list: | |||
635 | 652 | ||
636 | /* Since we are shutting down remove all pages from the buffer */ | 653 | /* Since we are shutting down remove all pages from the buffer */ |
637 | shrink_free_pagepool(blkif, 0 /* All */); | 654 | shrink_free_pagepool(blkif, 0 /* All */); |
638 | |||
639 | if (log_stats) | ||
640 | print_stats(blkif); | ||
641 | |||
642 | blkif->xenblkd = NULL; | ||
643 | xen_blkif_put(blkif); | ||
644 | |||
645 | return 0; | ||
646 | } | 655 | } |
647 | 656 | ||
648 | /* | 657 | /* |
diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 8d8807563d99..f733d7627120 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h | |||
@@ -376,6 +376,7 @@ int xen_blkif_xenbus_init(void); | |||
376 | irqreturn_t xen_blkif_be_int(int irq, void *dev_id); | 376 | irqreturn_t xen_blkif_be_int(int irq, void *dev_id); |
377 | int xen_blkif_schedule(void *arg); | 377 | int xen_blkif_schedule(void *arg); |
378 | int xen_blkif_purge_persistent(void *arg); | 378 | int xen_blkif_purge_persistent(void *arg); |
379 | void xen_blkbk_free_caches(struct xen_blkif *blkif); | ||
379 | 380 | ||
380 | int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt, | 381 | int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt, |
381 | struct backend_info *be, int state); | 382 | struct backend_info *be, int state); |
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index c2014a0aa206..8afef67fecdd 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c | |||
@@ -125,6 +125,7 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid) | |||
125 | blkif->persistent_gnts.rb_node = NULL; | 125 | blkif->persistent_gnts.rb_node = NULL; |
126 | spin_lock_init(&blkif->free_pages_lock); | 126 | spin_lock_init(&blkif->free_pages_lock); |
127 | INIT_LIST_HEAD(&blkif->free_pages); | 127 | INIT_LIST_HEAD(&blkif->free_pages); |
128 | INIT_LIST_HEAD(&blkif->persistent_purge_list); | ||
128 | blkif->free_pages_num = 0; | 129 | blkif->free_pages_num = 0; |
129 | atomic_set(&blkif->persistent_gnt_in_use, 0); | 130 | atomic_set(&blkif->persistent_gnt_in_use, 0); |
130 | 131 | ||
@@ -259,6 +260,17 @@ static void xen_blkif_free(struct xen_blkif *blkif) | |||
259 | if (!atomic_dec_and_test(&blkif->refcnt)) | 260 | if (!atomic_dec_and_test(&blkif->refcnt)) |
260 | BUG(); | 261 | BUG(); |
261 | 262 | ||
263 | /* Remove all persistent grants and the cache of ballooned pages. */ | ||
264 | xen_blkbk_free_caches(blkif); | ||
265 | |||
266 | /* Make sure everything is drained before shutting down */ | ||
267 | BUG_ON(blkif->persistent_gnt_c != 0); | ||
268 | BUG_ON(atomic_read(&blkif->persistent_gnt_in_use) != 0); | ||
269 | BUG_ON(blkif->free_pages_num != 0); | ||
270 | BUG_ON(!list_empty(&blkif->persistent_purge_list)); | ||
271 | BUG_ON(!list_empty(&blkif->free_pages)); | ||
272 | BUG_ON(!RB_EMPTY_ROOT(&blkif->persistent_gnts)); | ||
273 | |||
262 | /* Check that there is no request in use */ | 274 | /* Check that there is no request in use */ |
263 | list_for_each_entry_safe(req, n, &blkif->pending_free, free_list) { | 275 | list_for_each_entry_safe(req, n, &blkif->pending_free, free_list) { |
264 | list_del(&req->free_list); | 276 | list_del(&req->free_list); |