diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/block/xen-blkback/blkback.c | 13 | ||||
-rw-r--r-- | drivers/block/xen-blkback/common.h | 2 | ||||
-rw-r--r-- | drivers/block/xen-blkback/xenbus.c | 2 |
3 files changed, 16 insertions, 1 deletions
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 4119bcdefd1a..ea158fe0c9a4 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c | |||
@@ -571,6 +571,7 @@ int xen_blkif_schedule(void *arg) | |||
571 | struct xen_blkif *blkif = arg; | 571 | struct xen_blkif *blkif = arg; |
572 | struct xen_vbd *vbd = &blkif->vbd; | 572 | struct xen_vbd *vbd = &blkif->vbd; |
573 | unsigned long timeout; | 573 | unsigned long timeout; |
574 | int ret; | ||
574 | 575 | ||
575 | xen_blkif_get(blkif); | 576 | xen_blkif_get(blkif); |
576 | 577 | ||
@@ -599,8 +600,12 @@ int xen_blkif_schedule(void *arg) | |||
599 | blkif->waiting_reqs = 0; | 600 | blkif->waiting_reqs = 0; |
600 | smp_mb(); /* clear flag *before* checking for work */ | 601 | smp_mb(); /* clear flag *before* checking for work */ |
601 | 602 | ||
602 | if (do_block_io_op(blkif)) | 603 | ret = do_block_io_op(blkif); |
604 | if (ret > 0) | ||
603 | blkif->waiting_reqs = 1; | 605 | blkif->waiting_reqs = 1; |
606 | if (ret == -EACCES) | ||
607 | wait_event_interruptible(blkif->shutdown_wq, | ||
608 | kthread_should_stop()); | ||
604 | 609 | ||
605 | purge_gnt_list: | 610 | purge_gnt_list: |
606 | if (blkif->vbd.feature_gnt_persistent && | 611 | if (blkif->vbd.feature_gnt_persistent && |
@@ -1009,6 +1014,12 @@ __do_block_io_op(struct xen_blkif *blkif) | |||
1009 | rp = blk_rings->common.sring->req_prod; | 1014 | rp = blk_rings->common.sring->req_prod; |
1010 | rmb(); /* Ensure we see queued requests up to 'rp'. */ | 1015 | rmb(); /* Ensure we see queued requests up to 'rp'. */ |
1011 | 1016 | ||
1017 | if (RING_REQUEST_PROD_OVERFLOW(&blk_rings->common, rp)) { | ||
1018 | rc = blk_rings->common.rsp_prod_pvt; | ||
1019 | pr_warn(DRV_PFX "Frontend provided bogus ring requests (%d - %d = %d). Halting ring processing on dev=%04x\n", | ||
1020 | rp, rc, rp - rc, blkif->vbd.pdevice); | ||
1021 | return -EACCES; | ||
1022 | } | ||
1012 | while (rc != rp) { | 1023 | while (rc != rp) { |
1013 | 1024 | ||
1014 | if (RING_REQUEST_CONS_OVERFLOW(&blk_rings->common, rc)) | 1025 | if (RING_REQUEST_CONS_OVERFLOW(&blk_rings->common, rc)) |
diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index c6b4cb9af6c2..8d8807563d99 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h | |||
@@ -314,6 +314,8 @@ struct xen_blkif { | |||
314 | unsigned long long st_wr_sect; | 314 | unsigned long long st_wr_sect; |
315 | 315 | ||
316 | wait_queue_head_t waiting_to_free; | 316 | wait_queue_head_t waiting_to_free; |
317 | /* Thread shutdown wait queue. */ | ||
318 | wait_queue_head_t shutdown_wq; | ||
317 | }; | 319 | }; |
318 | 320 | ||
319 | struct seg_buf { | 321 | struct seg_buf { |
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 7b06f943371c..2e5b69d612ac 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c | |||
@@ -151,6 +151,7 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid) | |||
151 | } | 151 | } |
152 | spin_lock_init(&blkif->pending_free_lock); | 152 | spin_lock_init(&blkif->pending_free_lock); |
153 | init_waitqueue_head(&blkif->pending_free_wq); | 153 | init_waitqueue_head(&blkif->pending_free_wq); |
154 | init_waitqueue_head(&blkif->shutdown_wq); | ||
154 | 155 | ||
155 | return blkif; | 156 | return blkif; |
156 | 157 | ||
@@ -231,6 +232,7 @@ static void xen_blkif_disconnect(struct xen_blkif *blkif) | |||
231 | { | 232 | { |
232 | if (blkif->xenblkd) { | 233 | if (blkif->xenblkd) { |
233 | kthread_stop(blkif->xenblkd); | 234 | kthread_stop(blkif->xenblkd); |
235 | wake_up(&blkif->shutdown_wq); | ||
234 | blkif->xenblkd = NULL; | 236 | blkif->xenblkd = NULL; |
235 | } | 237 | } |
236 | 238 | ||