aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/xen-blkback/blkback.c13
-rw-r--r--drivers/block/xen-blkback/common.h2
-rw-r--r--drivers/block/xen-blkback/xenbus.c2
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
605purge_gnt_list: 610purge_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
319struct seg_buf { 321struct 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