|
@@ -571,6 +571,7 @@ int xen_blkif_schedule(void *arg)
|
|
|
struct xen_blkif *blkif = arg;
|
|
|
struct xen_vbd *vbd = &blkif->vbd;
|
|
|
unsigned long timeout;
|
|
|
+ int ret;
|
|
|
|
|
|
xen_blkif_get(blkif);
|
|
|
|
|
@@ -599,8 +600,12 @@ int xen_blkif_schedule(void *arg)
|
|
|
blkif->waiting_reqs = 0;
|
|
|
smp_mb(); /* clear flag *before* checking for work */
|
|
|
|
|
|
- if (do_block_io_op(blkif))
|
|
|
+ ret = do_block_io_op(blkif);
|
|
|
+ if (ret > 0)
|
|
|
blkif->waiting_reqs = 1;
|
|
|
+ if (ret == -EACCES)
|
|
|
+ wait_event_interruptible(blkif->shutdown_wq,
|
|
|
+ kthread_should_stop());
|
|
|
|
|
|
purge_gnt_list:
|
|
|
if (blkif->vbd.feature_gnt_persistent &&
|
|
@@ -1009,6 +1014,12 @@ __do_block_io_op(struct xen_blkif *blkif)
|
|
|
rp = blk_rings->common.sring->req_prod;
|
|
|
rmb(); /* Ensure we see queued requests up to 'rp'. */
|
|
|
|
|
|
+ if (RING_REQUEST_PROD_OVERFLOW(&blk_rings->common, rp)) {
|
|
|
+ rc = blk_rings->common.rsp_prod_pvt;
|
|
|
+ pr_warn(DRV_PFX "Frontend provided bogus ring requests (%d - %d = %d). Halting ring processing on dev=%04x\n",
|
|
|
+ rp, rc, rp - rc, blkif->vbd.pdevice);
|
|
|
+ return -EACCES;
|
|
|
+ }
|
|
|
while (rc != rp) {
|
|
|
|
|
|
if (RING_REQUEST_CONS_OVERFLOW(&blk_rings->common, rc))
|