Merge tag 'stable/for-linus-3.4-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen
Pull xen fixes from Konrad Rzeszutek Wilk: - mechanism to work with misconfigured backends (where they are advertised but in reality don't exist). - two tiny compile warning fixes. - proper error handling in gnttab_resume - Not using VM_PFNMAP anymore to allow backends in the same domain. * tag 'stable/for-linus-3.4-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen: Revert "xen/p2m: m2p_find_override: use list_for_each_entry_safe" xen/resume: Fix compile warnings. xen/xenbus: Add quirk to deal with misconfigured backends. xen/blkback: Fix warning error. xen/p2m: m2p_find_override: use list_for_each_entry_safe xen/gntdev: do not set VM_PFNMAP xen/grant-table: add error-handling code on failure of gnttab_resume
This commit is contained in:
@@ -416,7 +416,7 @@ static void xen_blkbk_discard(struct xenbus_transaction xbt, struct backend_info
|
|||||||
"discard-secure", "%d",
|
"discard-secure", "%d",
|
||||||
blkif->vbd.discard_secure);
|
blkif->vbd.discard_secure);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_warn(dev-dev, "writing discard-secure (%d)", err);
|
dev_warn(&dev->dev, "writing discard-secure (%d)", err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -722,7 +722,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
|
|||||||
vma->vm_flags |= VM_RESERVED|VM_DONTEXPAND;
|
vma->vm_flags |= VM_RESERVED|VM_DONTEXPAND;
|
||||||
|
|
||||||
if (use_ptemod)
|
if (use_ptemod)
|
||||||
vma->vm_flags |= VM_DONTCOPY|VM_PFNMAP;
|
vma->vm_flags |= VM_DONTCOPY;
|
||||||
|
|
||||||
vma->vm_private_data = map;
|
vma->vm_private_data = map;
|
||||||
|
|
||||||
|
@@ -1029,6 +1029,7 @@ int gnttab_init(void)
|
|||||||
int i;
|
int i;
|
||||||
unsigned int max_nr_glist_frames, nr_glist_frames;
|
unsigned int max_nr_glist_frames, nr_glist_frames;
|
||||||
unsigned int nr_init_grefs;
|
unsigned int nr_init_grefs;
|
||||||
|
int ret;
|
||||||
|
|
||||||
nr_grant_frames = 1;
|
nr_grant_frames = 1;
|
||||||
boot_max_nr_grant_frames = __max_nr_grant_frames();
|
boot_max_nr_grant_frames = __max_nr_grant_frames();
|
||||||
@@ -1047,12 +1048,16 @@ int gnttab_init(void)
|
|||||||
nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
|
nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
|
||||||
for (i = 0; i < nr_glist_frames; i++) {
|
for (i = 0; i < nr_glist_frames; i++) {
|
||||||
gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL);
|
gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL);
|
||||||
if (gnttab_list[i] == NULL)
|
if (gnttab_list[i] == NULL) {
|
||||||
|
ret = -ENOMEM;
|
||||||
goto ini_nomem;
|
goto ini_nomem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gnttab_resume() < 0)
|
if (gnttab_resume() < 0) {
|
||||||
return -ENODEV;
|
ret = -ENODEV;
|
||||||
|
goto ini_nomem;
|
||||||
|
}
|
||||||
|
|
||||||
nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME;
|
nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME;
|
||||||
|
|
||||||
@@ -1070,7 +1075,7 @@ int gnttab_init(void)
|
|||||||
for (i--; i >= 0; i--)
|
for (i--; i >= 0; i--)
|
||||||
free_page((unsigned long)gnttab_list[i]);
|
free_page((unsigned long)gnttab_list[i]);
|
||||||
kfree(gnttab_list);
|
kfree(gnttab_list);
|
||||||
return -ENOMEM;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(gnttab_init);
|
EXPORT_SYMBOL_GPL(gnttab_init);
|
||||||
|
|
||||||
|
@@ -132,6 +132,7 @@ static void do_suspend(void)
|
|||||||
err = dpm_suspend_end(PMSG_FREEZE);
|
err = dpm_suspend_end(PMSG_FREEZE);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR "dpm_suspend_end failed: %d\n", err);
|
printk(KERN_ERR "dpm_suspend_end failed: %d\n", err);
|
||||||
|
si.cancelled = 0;
|
||||||
goto out_resume;
|
goto out_resume;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -135,7 +135,7 @@ static int read_backend_details(struct xenbus_device *xendev)
|
|||||||
return xenbus_read_otherend_details(xendev, "backend-id", "backend");
|
return xenbus_read_otherend_details(xendev, "backend-id", "backend");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_device_connecting(struct device *dev, void *data)
|
static int is_device_connecting(struct device *dev, void *data, bool ignore_nonessential)
|
||||||
{
|
{
|
||||||
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;
|
||||||
@@ -152,16 +152,41 @@ static int is_device_connecting(struct device *dev, void *data)
|
|||||||
if (drv && (dev->driver != drv))
|
if (drv && (dev->driver != drv))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (ignore_nonessential) {
|
||||||
|
/* With older QEMU, for PVonHVM guests the guest config files
|
||||||
|
* could contain: vfb = [ 'vnc=1, vnclisten=0.0.0.0']
|
||||||
|
* which is nonsensical as there is no PV FB (there can be
|
||||||
|
* a PVKB) running as HVM guest. */
|
||||||
|
|
||||||
|
if ((strncmp(xendev->nodename, "device/vkbd", 11) == 0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ((strncmp(xendev->nodename, "device/vfb", 10) == 0))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
xendrv = to_xenbus_driver(dev->driver);
|
xendrv = to_xenbus_driver(dev->driver);
|
||||||
return (xendev->state < XenbusStateConnected ||
|
return (xendev->state < XenbusStateConnected ||
|
||||||
(xendev->state == XenbusStateConnected &&
|
(xendev->state == XenbusStateConnected &&
|
||||||
xendrv->is_ready && !xendrv->is_ready(xendev)));
|
xendrv->is_ready && !xendrv->is_ready(xendev)));
|
||||||
}
|
}
|
||||||
|
static int essential_device_connecting(struct device *dev, void *data)
|
||||||
|
{
|
||||||
|
return is_device_connecting(dev, data, true /* ignore PV[KBB+FB] */);
|
||||||
|
}
|
||||||
|
static int non_essential_device_connecting(struct device *dev, void *data)
|
||||||
|
{
|
||||||
|
return is_device_connecting(dev, data, false);
|
||||||
|
}
|
||||||
|
|
||||||
static int exists_connecting_device(struct device_driver *drv)
|
static int exists_essential_connecting_device(struct device_driver *drv)
|
||||||
{
|
{
|
||||||
return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
|
return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
|
||||||
is_device_connecting);
|
essential_device_connecting);
|
||||||
|
}
|
||||||
|
static int exists_non_essential_connecting_device(struct device_driver *drv)
|
||||||
|
{
|
||||||
|
return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
|
||||||
|
non_essential_device_connecting);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int print_device_status(struct device *dev, void *data)
|
static int print_device_status(struct device *dev, void *data)
|
||||||
@@ -192,6 +217,23 @@ static int print_device_status(struct device *dev, void *data)
|
|||||||
/* We only wait for device setup after most initcalls have run. */
|
/* We only wait for device setup after most initcalls have run. */
|
||||||
static int ready_to_wait_for_devices;
|
static int ready_to_wait_for_devices;
|
||||||
|
|
||||||
|
static bool wait_loop(unsigned long start, unsigned int max_delay,
|
||||||
|
unsigned int *seconds_waited)
|
||||||
|
{
|
||||||
|
if (time_after(jiffies, start + (*seconds_waited+5)*HZ)) {
|
||||||
|
if (!*seconds_waited)
|
||||||
|
printk(KERN_WARNING "XENBUS: Waiting for "
|
||||||
|
"devices to initialise: ");
|
||||||
|
*seconds_waited += 5;
|
||||||
|
printk("%us...", max_delay - *seconds_waited);
|
||||||
|
if (*seconds_waited == max_delay)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
schedule_timeout_interruptible(HZ/10);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* On a 5-minute timeout, wait for all devices currently configured. We need
|
* On a 5-minute timeout, wait for all devices currently configured. We need
|
||||||
* to do this to guarantee that the filesystems and / or network devices
|
* to do this to guarantee that the filesystems and / or network devices
|
||||||
@@ -215,19 +257,14 @@ static void wait_for_devices(struct xenbus_driver *xendrv)
|
|||||||
if (!ready_to_wait_for_devices || !xen_domain())
|
if (!ready_to_wait_for_devices || !xen_domain())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (exists_connecting_device(drv)) {
|
while (exists_non_essential_connecting_device(drv))
|
||||||
if (time_after(jiffies, start + (seconds_waited+5)*HZ)) {
|
if (wait_loop(start, 30, &seconds_waited))
|
||||||
if (!seconds_waited)
|
break;
|
||||||
printk(KERN_WARNING "XENBUS: Waiting for "
|
|
||||||
"devices to initialise: ");
|
|
||||||
seconds_waited += 5;
|
|
||||||
printk("%us...", 300 - seconds_waited);
|
|
||||||
if (seconds_waited == 300)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
schedule_timeout_interruptible(HZ/10);
|
/* Skips PVKB and PVFB check.*/
|
||||||
}
|
while (exists_essential_connecting_device(drv))
|
||||||
|
if (wait_loop(start, 270, &seconds_waited))
|
||||||
|
break;
|
||||||
|
|
||||||
if (seconds_waited)
|
if (seconds_waited)
|
||||||
printk("\n");
|
printk("\n");
|
||||||
|
Reference in New Issue
Block a user