Skip to content

Commit 71b6624

Browse files
committed
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: Juergen Gross <jgross@suse.com> Reviewed-by: Jan Beulich <jbeulich@suse.com> Acked-by: Roger Pau Monné <roger.pau@citrix.com> Link: https://lore.kernel.org/r/20210730103854.12681-2-jgross@suse.com Signed-off-by: Juergen Gross <jgross@suse.com>
1 parent 30dcc56 commit 71b6624

1 file changed

Lines changed: 18 additions & 17 deletions

File tree

drivers/block/xen-blkfront.c

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1496,7 +1496,7 @@ static bool blkif_completion(unsigned long *id,
14961496
static irqreturn_t blkif_interrupt(int irq, void *dev_id)
14971497
{
14981498
struct request *req;
1499-
struct blkif_response *bret;
1499+
struct blkif_response bret;
15001500
RING_IDX i, rp;
15011501
unsigned long flags;
15021502
struct blkfront_ring_info *rinfo = (struct blkfront_ring_info *)dev_id;
@@ -1513,48 +1513,49 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
15131513
for (i = rinfo->ring.rsp_cons; i != rp; i++) {
15141514
unsigned long id;
15151515

1516-
bret = RING_GET_RESPONSE(&rinfo->ring, i);
1517-
id = bret->id;
1516+
RING_COPY_RESPONSE(&rinfo->ring, i, &bret);
1517+
id = bret.id;
1518+
15181519
/*
15191520
* The backend has messed up and given us an id that we would
15201521
* never have given to it (we stamp it up to BLK_RING_SIZE -
15211522
* look in get_id_from_freelist.
15221523
*/
15231524
if (id >= BLK_RING_SIZE(info)) {
15241525
WARN(1, "%s: response to %s has incorrect id (%ld)\n",
1525-
info->gd->disk_name, op_name(bret->operation), id);
1526+
info->gd->disk_name, op_name(bret.operation), id);
15261527
/* We can't safely get the 'struct request' as
15271528
* the id is busted. */
15281529
continue;
15291530
}
15301531
req = rinfo->shadow[id].request;
15311532

1532-
if (bret->operation != BLKIF_OP_DISCARD) {
1533+
if (bret.operation != BLKIF_OP_DISCARD) {
15331534
/*
15341535
* We may need to wait for an extra response if the
15351536
* I/O request is split in 2
15361537
*/
1537-
if (!blkif_completion(&id, rinfo, bret))
1538+
if (!blkif_completion(&id, rinfo, &bret))
15381539
continue;
15391540
}
15401541

15411542
if (add_id_to_freelist(rinfo, id)) {
15421543
WARN(1, "%s: response to %s (id %ld) couldn't be recycled!\n",
1543-
info->gd->disk_name, op_name(bret->operation), id);
1544+
info->gd->disk_name, op_name(bret.operation), id);
15441545
continue;
15451546
}
15461547

1547-
if (bret->status == BLKIF_RSP_OKAY)
1548+
if (bret.status == BLKIF_RSP_OKAY)
15481549
blkif_req(req)->error = BLK_STS_OK;
15491550
else
15501551
blkif_req(req)->error = BLK_STS_IOERR;
15511552

1552-
switch (bret->operation) {
1553+
switch (bret.operation) {
15531554
case BLKIF_OP_DISCARD:
1554-
if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
1555+
if (unlikely(bret.status == BLKIF_RSP_EOPNOTSUPP)) {
15551556
struct request_queue *rq = info->rq;
15561557
printk(KERN_WARNING "blkfront: %s: %s op failed\n",
1557-
info->gd->disk_name, op_name(bret->operation));
1558+
info->gd->disk_name, op_name(bret.operation));
15581559
blkif_req(req)->error = BLK_STS_NOTSUPP;
15591560
info->feature_discard = 0;
15601561
info->feature_secdiscard = 0;
@@ -1564,15 +1565,15 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
15641565
break;
15651566
case BLKIF_OP_FLUSH_DISKCACHE:
15661567
case BLKIF_OP_WRITE_BARRIER:
1567-
if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
1568+
if (unlikely(bret.status == BLKIF_RSP_EOPNOTSUPP)) {
15681569
printk(KERN_WARNING "blkfront: %s: %s op failed\n",
1569-
info->gd->disk_name, op_name(bret->operation));
1570+
info->gd->disk_name, op_name(bret.operation));
15701571
blkif_req(req)->error = BLK_STS_NOTSUPP;
15711572
}
1572-
if (unlikely(bret->status == BLKIF_RSP_ERROR &&
1573+
if (unlikely(bret.status == BLKIF_RSP_ERROR &&
15731574
rinfo->shadow[id].req.u.rw.nr_segments == 0)) {
15741575
printk(KERN_WARNING "blkfront: %s: empty %s op failed\n",
1575-
info->gd->disk_name, op_name(bret->operation));
1576+
info->gd->disk_name, op_name(bret.operation));
15761577
blkif_req(req)->error = BLK_STS_NOTSUPP;
15771578
}
15781579
if (unlikely(blkif_req(req)->error)) {
@@ -1585,9 +1586,9 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
15851586
fallthrough;
15861587
case BLKIF_OP_READ:
15871588
case BLKIF_OP_WRITE:
1588-
if (unlikely(bret->status != BLKIF_RSP_OKAY))
1589+
if (unlikely(bret.status != BLKIF_RSP_OKAY))
15891590
dev_dbg(&info->xbdev->dev, "Bad return from blkdev data "
1590-
"request: %x\n", bret->status);
1591+
"request: %x\n", bret.status);
15911592

15921593
break;
15931594
default:

0 commit comments

Comments
 (0)