diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2008-03-26 13:15:00 +0000 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2008-03-26 13:15:00 +0000 |
commit | d3ca7ebeccd4a93deea2c2eadee40c0b3be57aeb (patch) | |
tree | 57f611598b750ba7683d1ba7d2f3a4a3fe45c500 /extras/mini-os/blkfront.c | |
parent | aecea1aa6522c44d8111731c8b6f0e9a6e08f001 (diff) | |
download | xen-d3ca7ebeccd4a93deea2c2eadee40c0b3be57aeb.tar.gz xen-d3ca7ebeccd4a93deea2c2eadee40c0b3be57aeb.tar.bz2 xen-d3ca7ebeccd4a93deea2c2eadee40c0b3be57aeb.zip |
minios: blkfront_aio_poll may reenter
if the callback calls blkfront_sync for instance.
In such a case, we would see responses and hence release grants
several times. We need to be more synchronous and stop when we detect
that we have re-entered.
This fixes HVM restore with stubdomains.
Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
Diffstat (limited to 'extras/mini-os/blkfront.c')
-rw-r--r-- | extras/mini-os/blkfront.c | 21 |
1 files changed, 12 insertions, 9 deletions
diff --git a/extras/mini-os/blkfront.c b/extras/mini-os/blkfront.c index 3a6c22aceb..b227f06247 100644 --- a/extras/mini-os/blkfront.c +++ b/extras/mini-os/blkfront.c @@ -319,6 +319,7 @@ int blkfront_aio_poll(struct blkfront_dev *dev) { RING_IDX rp, cons; struct blkif_response *rsp; + int more; moretodo: #ifdef HAVE_LIBC @@ -334,6 +335,7 @@ moretodo: while ((cons != rp)) { rsp = RING_GET_RESPONSE(&dev->ring, cons); + nr_consumed++; if (rsp->status != BLKIF_RSP_OKAY) printk("block error %d for op %d\n", rsp->status, rsp->operation); @@ -343,29 +345,30 @@ moretodo: case BLKIF_OP_WRITE: { struct blkfront_aiocb *aiocbp = (void*) (uintptr_t) rsp->id; + int status = rsp->status; int j; for (j = 0; j < aiocbp->n; j++) gnttab_end_access(aiocbp->gref[j]); + dev->ring.rsp_cons = ++cons; /* Nota: callback frees aiocbp itself */ - aiocbp->aio_cb(aiocbp, rsp->status ? -EIO : 0); + aiocbp->aio_cb(aiocbp, status ? -EIO : 0); + if (dev->ring.rsp_cons != cons) + /* We reentered, we must not continue here */ + goto out; break; } - case BLKIF_OP_WRITE_BARRIER: - case BLKIF_OP_FLUSH_DISKCACHE: - break; default: printk("unrecognized block operation %d response\n", rsp->operation); + case BLKIF_OP_WRITE_BARRIER: + case BLKIF_OP_FLUSH_DISKCACHE: + dev->ring.rsp_cons = ++cons; break; } - - nr_consumed++; - ++cons; } - dev->ring.rsp_cons = cons; - int more; +out: RING_FINAL_CHECK_FOR_RESPONSES(&dev->ring, more); if (more) goto moretodo; |