Commit 1d78d705 authored by Christian Limpach's avatar Christian Limpach Committed by Ingo Molnar

xen blkfront: Delay wait for block devices until after the disk is added

When the xen block frontend driver is built as a module the module load
is only synchronous up to the point where the frontend and the backend
become connected rather than when the disk is added.

This means that there can be a race on boot between loading the module and
loading the dm-* modules and doing the scan for LVM physical volumes (all
in the initrd). In the failure case the disk is not present until after the
scan for physical volumes is complete.

Taken from:

  http://xenbits.xensource.com/linux-2.6.18-xen.hg?rev/11483a00c017Signed-off-by: default avatarChristian Limpach <Christian.Limpach@xensource.com>
Signed-off-by: default avatarMark McLoughlin <markmc@redhat.com>
Signed-off-by: default avatarJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 53f0e8af
...@@ -88,6 +88,7 @@ struct blkfront_info ...@@ -88,6 +88,7 @@ struct blkfront_info
struct blk_shadow shadow[BLK_RING_SIZE]; struct blk_shadow shadow[BLK_RING_SIZE];
unsigned long shadow_free; unsigned long shadow_free;
int feature_barrier; int feature_barrier;
int is_ready;
/** /**
* The number of people holding this device open. We won't allow a * The number of people holding this device open. We won't allow a
...@@ -839,6 +840,8 @@ static void blkfront_connect(struct blkfront_info *info) ...@@ -839,6 +840,8 @@ static void blkfront_connect(struct blkfront_info *info)
spin_unlock_irq(&blkif_io_lock); spin_unlock_irq(&blkif_io_lock);
add_disk(info->gd); add_disk(info->gd);
info->is_ready = 1;
} }
/** /**
...@@ -931,6 +934,13 @@ static int blkfront_remove(struct xenbus_device *dev) ...@@ -931,6 +934,13 @@ static int blkfront_remove(struct xenbus_device *dev)
return 0; return 0;
} }
static int blkfront_is_ready(struct xenbus_device *dev)
{
struct blkfront_info *info = dev->dev.driver_data;
return info->is_ready;
}
static int blkif_open(struct inode *inode, struct file *filep) static int blkif_open(struct inode *inode, struct file *filep)
{ {
struct blkfront_info *info = inode->i_bdev->bd_disk->private_data; struct blkfront_info *info = inode->i_bdev->bd_disk->private_data;
...@@ -977,6 +987,7 @@ static struct xenbus_driver blkfront = { ...@@ -977,6 +987,7 @@ static struct xenbus_driver blkfront = {
.remove = blkfront_remove, .remove = blkfront_remove,
.resume = blkfront_resume, .resume = blkfront_resume,
.otherend_changed = backend_changed, .otherend_changed = backend_changed,
.is_ready = blkfront_is_ready,
}; };
static int __init xlblk_init(void) static int __init xlblk_init(void)
......
...@@ -846,6 +846,7 @@ static int is_disconnected_device(struct device *dev, void *data) ...@@ -846,6 +846,7 @@ static int is_disconnected_device(struct device *dev, void *data)
{ {
struct xenbus_device *xendev = to_xenbus_device(dev); struct xenbus_device *xendev = to_xenbus_device(dev);
struct device_driver *drv = data; struct device_driver *drv = data;
struct xenbus_driver *xendrv;
/* /*
* A device with no driver will never connect. We care only about * A device with no driver will never connect. We care only about
...@@ -858,7 +859,9 @@ static int is_disconnected_device(struct device *dev, void *data) ...@@ -858,7 +859,9 @@ static int is_disconnected_device(struct device *dev, void *data)
if (drv && (dev->driver != drv)) if (drv && (dev->driver != drv))
return 0; return 0;
return (xendev->state != XenbusStateConnected); xendrv = to_xenbus_driver(dev->driver);
return (xendev->state != XenbusStateConnected ||
(xendrv->is_ready && !xendrv->is_ready(xendev)));
} }
static int exists_disconnected_device(struct device_driver *drv) static int exists_disconnected_device(struct device_driver *drv)
......
...@@ -97,6 +97,7 @@ struct xenbus_driver { ...@@ -97,6 +97,7 @@ struct xenbus_driver {
int (*uevent)(struct xenbus_device *, char **, int, char *, int); int (*uevent)(struct xenbus_device *, char **, int, char *, int);
struct device_driver driver; struct device_driver driver;
int (*read_otherend_details)(struct xenbus_device *dev); int (*read_otherend_details)(struct xenbus_device *dev);
int (*is_ready)(struct xenbus_device *dev);
}; };
static inline struct xenbus_driver *to_xenbus_driver(struct device_driver *drv) static inline struct xenbus_driver *to_xenbus_driver(struct device_driver *drv)
......
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