Commit 71b66243 authored by Juergen Gross's avatar Juergen Gross

xen/blkfront: read response from backend only once

In order to avoid problems in case the backend is modifying a response
on the ring page while the frontend has already seen it, just read the
response into a local buffer in one go and then operate on that buffer
only.
Signed-off-by: default avatarJuergen Gross <jgross@suse.com>
Reviewed-by: default avatarJan Beulich <jbeulich@suse.com>
Acked-by: default avatarRoger Pau Monné <roger.pau@citrix.com>
Link: https://lore.kernel.org/r/20210730103854.12681-2-jgross@suse.comSigned-off-by: default avatarJuergen Gross <jgross@suse.com>
parent 30dcc56b
...@@ -1496,7 +1496,7 @@ static bool blkif_completion(unsigned long *id, ...@@ -1496,7 +1496,7 @@ static bool blkif_completion(unsigned long *id,
static irqreturn_t blkif_interrupt(int irq, void *dev_id) static irqreturn_t blkif_interrupt(int irq, void *dev_id)
{ {
struct request *req; struct request *req;
struct blkif_response *bret; struct blkif_response bret;
RING_IDX i, rp; RING_IDX i, rp;
unsigned long flags; unsigned long flags;
struct blkfront_ring_info *rinfo = (struct blkfront_ring_info *)dev_id; struct blkfront_ring_info *rinfo = (struct blkfront_ring_info *)dev_id;
...@@ -1513,8 +1513,9 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) ...@@ -1513,8 +1513,9 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
for (i = rinfo->ring.rsp_cons; i != rp; i++) { for (i = rinfo->ring.rsp_cons; i != rp; i++) {
unsigned long id; unsigned long id;
bret = RING_GET_RESPONSE(&rinfo->ring, i); RING_COPY_RESPONSE(&rinfo->ring, i, &bret);
id = bret->id; id = bret.id;
/* /*
* The backend has messed up and given us an id that we would * The backend has messed up and given us an id that we would
* never have given to it (we stamp it up to BLK_RING_SIZE - * never have given to it (we stamp it up to BLK_RING_SIZE -
...@@ -1522,39 +1523,39 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) ...@@ -1522,39 +1523,39 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
*/ */
if (id >= BLK_RING_SIZE(info)) { if (id >= BLK_RING_SIZE(info)) {
WARN(1, "%s: response to %s has incorrect id (%ld)\n", WARN(1, "%s: response to %s has incorrect id (%ld)\n",
info->gd->disk_name, op_name(bret->operation), id); info->gd->disk_name, op_name(bret.operation), id);
/* We can't safely get the 'struct request' as /* We can't safely get the 'struct request' as
* the id is busted. */ * the id is busted. */
continue; continue;
} }
req = rinfo->shadow[id].request; req = rinfo->shadow[id].request;
if (bret->operation != BLKIF_OP_DISCARD) { if (bret.operation != BLKIF_OP_DISCARD) {
/* /*
* We may need to wait for an extra response if the * We may need to wait for an extra response if the
* I/O request is split in 2 * I/O request is split in 2
*/ */
if (!blkif_completion(&id, rinfo, bret)) if (!blkif_completion(&id, rinfo, &bret))
continue; continue;
} }
if (add_id_to_freelist(rinfo, id)) { if (add_id_to_freelist(rinfo, id)) {
WARN(1, "%s: response to %s (id %ld) couldn't be recycled!\n", WARN(1, "%s: response to %s (id %ld) couldn't be recycled!\n",
info->gd->disk_name, op_name(bret->operation), id); info->gd->disk_name, op_name(bret.operation), id);
continue; continue;
} }
if (bret->status == BLKIF_RSP_OKAY) if (bret.status == BLKIF_RSP_OKAY)
blkif_req(req)->error = BLK_STS_OK; blkif_req(req)->error = BLK_STS_OK;
else else
blkif_req(req)->error = BLK_STS_IOERR; blkif_req(req)->error = BLK_STS_IOERR;
switch (bret->operation) { switch (bret.operation) {
case BLKIF_OP_DISCARD: case BLKIF_OP_DISCARD:
if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) { if (unlikely(bret.status == BLKIF_RSP_EOPNOTSUPP)) {
struct request_queue *rq = info->rq; struct request_queue *rq = info->rq;
printk(KERN_WARNING "blkfront: %s: %s op failed\n", printk(KERN_WARNING "blkfront: %s: %s op failed\n",
info->gd->disk_name, op_name(bret->operation)); info->gd->disk_name, op_name(bret.operation));
blkif_req(req)->error = BLK_STS_NOTSUPP; blkif_req(req)->error = BLK_STS_NOTSUPP;
info->feature_discard = 0; info->feature_discard = 0;
info->feature_secdiscard = 0; info->feature_secdiscard = 0;
...@@ -1564,15 +1565,15 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) ...@@ -1564,15 +1565,15 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
break; break;
case BLKIF_OP_FLUSH_DISKCACHE: case BLKIF_OP_FLUSH_DISKCACHE:
case BLKIF_OP_WRITE_BARRIER: case BLKIF_OP_WRITE_BARRIER:
if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) { if (unlikely(bret.status == BLKIF_RSP_EOPNOTSUPP)) {
printk(KERN_WARNING "blkfront: %s: %s op failed\n", printk(KERN_WARNING "blkfront: %s: %s op failed\n",
info->gd->disk_name, op_name(bret->operation)); info->gd->disk_name, op_name(bret.operation));
blkif_req(req)->error = BLK_STS_NOTSUPP; blkif_req(req)->error = BLK_STS_NOTSUPP;
} }
if (unlikely(bret->status == BLKIF_RSP_ERROR && if (unlikely(bret.status == BLKIF_RSP_ERROR &&
rinfo->shadow[id].req.u.rw.nr_segments == 0)) { rinfo->shadow[id].req.u.rw.nr_segments == 0)) {
printk(KERN_WARNING "blkfront: %s: empty %s op failed\n", printk(KERN_WARNING "blkfront: %s: empty %s op failed\n",
info->gd->disk_name, op_name(bret->operation)); info->gd->disk_name, op_name(bret.operation));
blkif_req(req)->error = BLK_STS_NOTSUPP; blkif_req(req)->error = BLK_STS_NOTSUPP;
} }
if (unlikely(blkif_req(req)->error)) { if (unlikely(blkif_req(req)->error)) {
...@@ -1585,9 +1586,9 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) ...@@ -1585,9 +1586,9 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
fallthrough; fallthrough;
case BLKIF_OP_READ: case BLKIF_OP_READ:
case BLKIF_OP_WRITE: case BLKIF_OP_WRITE:
if (unlikely(bret->status != BLKIF_RSP_OKAY)) if (unlikely(bret.status != BLKIF_RSP_OKAY))
dev_dbg(&info->xbdev->dev, "Bad return from blkdev data " dev_dbg(&info->xbdev->dev, "Bad return from blkdev data "
"request: %x\n", bret->status); "request: %x\n", bret.status);
break; break;
default: default:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment