xen/xenbus: fix locking
Commit060eabe8fb
("xenbus/backend: Protect xenbus callback with lock") introduced a bug by holding a lock while calling a function which might schedule. Fix that by using a semaphore instead. Fixes:060eabe8fb
("xenbus/backend: Protect xenbus callback with lock") Signed-off-by: Juergen Gross <jgross@suse.com> Link: https://lore.kernel.org/r/20200305100323.16736-1-jgross@suse.com Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
This commit is contained in:

committed by
Boris Ostrovsky

parent
8130b9d5b5
commit
2f69a110e7
@@ -239,9 +239,9 @@ int xenbus_dev_probe(struct device *_dev)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock(&dev->reclaim_lock);
|
down(&dev->reclaim_sem);
|
||||||
err = drv->probe(dev, id);
|
err = drv->probe(dev, id);
|
||||||
spin_unlock(&dev->reclaim_lock);
|
up(&dev->reclaim_sem);
|
||||||
if (err)
|
if (err)
|
||||||
goto fail_put;
|
goto fail_put;
|
||||||
|
|
||||||
@@ -271,9 +271,9 @@ int xenbus_dev_remove(struct device *_dev)
|
|||||||
free_otherend_watch(dev);
|
free_otherend_watch(dev);
|
||||||
|
|
||||||
if (drv->remove) {
|
if (drv->remove) {
|
||||||
spin_lock(&dev->reclaim_lock);
|
down(&dev->reclaim_sem);
|
||||||
drv->remove(dev);
|
drv->remove(dev);
|
||||||
spin_unlock(&dev->reclaim_lock);
|
up(&dev->reclaim_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_put(drv->driver.owner);
|
module_put(drv->driver.owner);
|
||||||
@@ -473,7 +473,7 @@ int xenbus_probe_node(struct xen_bus_type *bus,
|
|||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
dev_set_name(&xendev->dev, "%s", devname);
|
dev_set_name(&xendev->dev, "%s", devname);
|
||||||
spin_lock_init(&xendev->reclaim_lock);
|
sema_init(&xendev->reclaim_sem, 1);
|
||||||
|
|
||||||
/* Register with generic device framework. */
|
/* Register with generic device framework. */
|
||||||
err = device_register(&xendev->dev);
|
err = device_register(&xendev->dev);
|
||||||
|
@@ -45,6 +45,7 @@
|
|||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/notifier.h>
|
#include <linux/notifier.h>
|
||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
|
#include <linux/semaphore.h>
|
||||||
|
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
@@ -257,10 +258,10 @@ static int backend_reclaim_memory(struct device *dev, void *data)
|
|||||||
drv = to_xenbus_driver(dev->driver);
|
drv = to_xenbus_driver(dev->driver);
|
||||||
if (drv && drv->reclaim_memory) {
|
if (drv && drv->reclaim_memory) {
|
||||||
xdev = to_xenbus_device(dev);
|
xdev = to_xenbus_device(dev);
|
||||||
if (!spin_trylock(&xdev->reclaim_lock))
|
if (down_trylock(&xdev->reclaim_sem))
|
||||||
return 0;
|
return 0;
|
||||||
drv->reclaim_memory(xdev);
|
drv->reclaim_memory(xdev);
|
||||||
spin_unlock(&xdev->reclaim_lock);
|
up(&xdev->reclaim_sem);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -42,6 +42,7 @@
|
|||||||
#include <linux/completion.h>
|
#include <linux/completion.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
#include <linux/semaphore.h>
|
||||||
#include <xen/interface/xen.h>
|
#include <xen/interface/xen.h>
|
||||||
#include <xen/interface/grant_table.h>
|
#include <xen/interface/grant_table.h>
|
||||||
#include <xen/interface/io/xenbus.h>
|
#include <xen/interface/io/xenbus.h>
|
||||||
@@ -76,7 +77,7 @@ struct xenbus_device {
|
|||||||
enum xenbus_state state;
|
enum xenbus_state state;
|
||||||
struct completion down;
|
struct completion down;
|
||||||
struct work_struct work;
|
struct work_struct work;
|
||||||
spinlock_t reclaim_lock;
|
struct semaphore reclaim_sem;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct xenbus_device *to_xenbus_device(struct device *dev)
|
static inline struct xenbus_device *to_xenbus_device(struct device *dev)
|
||||||
|
Reference in New Issue
Block a user