xen/blkfront: Fix crash if backend doesn't follow the right states.
We have split the setting up of all the resources in two steps: 1) talk_to_blkback - which figures out the num_ring_pages (from the default value of zero), sets up shadow and so 2) blkfront_connect - does the real part of filling out the internal structures. The problem is if we bypass the 1) step and go straight to 2) and call blkfront_setup_indirect where we use the macro BLK_RING_SIZE - which returns an negative value (because sz is zero - since num_ring_pages is zero - since it has never been set). We can fix this by making sure that we always have called talk_to_blkback before going to blkfront_connect. Or we could set in blkfront_probe info->nr_ring_pages = 1 to have a default value. But that looks odd - as we haven't actually negotiated any ring size. This patch changes XenbusStateConnected state to detect if we haven't done the initial handshake - and if so continue on as if were in XenbusStateInitWait state. We also roll the error recovery (freeing the structure) into talk_to_blkback error path - which is safe since that function is only called from blkback_changed. Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
This commit is contained in:
parent
93bb277f97
commit
c31ecf6c12
1 changed files with 8 additions and 4 deletions
|
@ -1867,6 +1867,9 @@ again:
|
||||||
destroy_blkring:
|
destroy_blkring:
|
||||||
blkif_free(info, 0);
|
blkif_free(info, 0);
|
||||||
|
|
||||||
|
kfree(info);
|
||||||
|
dev_set_drvdata(&dev->dev, NULL);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2453,11 +2456,8 @@ static void blkback_changed(struct xenbus_device *dev,
|
||||||
case XenbusStateInitWait:
|
case XenbusStateInitWait:
|
||||||
if (dev->state != XenbusStateInitialising)
|
if (dev->state != XenbusStateInitialising)
|
||||||
break;
|
break;
|
||||||
if (talk_to_blkback(dev, info)) {
|
if (talk_to_blkback(dev, info))
|
||||||
kfree(info);
|
|
||||||
dev_set_drvdata(&dev->dev, NULL);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case XenbusStateInitialising:
|
case XenbusStateInitialising:
|
||||||
case XenbusStateInitialised:
|
case XenbusStateInitialised:
|
||||||
case XenbusStateReconfiguring:
|
case XenbusStateReconfiguring:
|
||||||
|
@ -2466,6 +2466,10 @@ static void blkback_changed(struct xenbus_device *dev,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XenbusStateConnected:
|
case XenbusStateConnected:
|
||||||
|
if (dev->state != XenbusStateInitialised) {
|
||||||
|
if (talk_to_blkback(dev, info))
|
||||||
|
break;
|
||||||
|
}
|
||||||
blkfront_connect(info);
|
blkfront_connect(info);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue