Skip to content

Commit 060eabe

Browse files
sj-awsbostrovs
authored andcommitted
xenbus/backend: Protect xenbus callback with lock
A driver's 'reclaim_memory' callback can race with 'probe' or 'remove' because it will be called whenever memory pressure is detected. To avoid such race, this commit embeds a spinlock in each 'xenbus_device' and make 'xenbus' to hold the lock while the corresponded callbacks are running. Reviewed-by: Juergen Gross <[email protected]> Signed-off-by: SeongJae Park <[email protected]> Signed-off-by: Boris Ostrovsky <[email protected]>
1 parent 8a10567 commit 060eabe

File tree

3 files changed

+16
-3
lines changed

3 files changed

+16
-3
lines changed

drivers/xen/xenbus/xenbus_probe.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,9 @@ int xenbus_dev_probe(struct device *_dev)
239239
goto fail;
240240
}
241241

242+
spin_lock(&dev->reclaim_lock);
242243
err = drv->probe(dev, id);
244+
spin_unlock(&dev->reclaim_lock);
243245
if (err)
244246
goto fail_put;
245247

@@ -268,8 +270,11 @@ int xenbus_dev_remove(struct device *_dev)
268270

269271
free_otherend_watch(dev);
270272

271-
if (drv->remove)
273+
if (drv->remove) {
274+
spin_lock(&dev->reclaim_lock);
272275
drv->remove(dev);
276+
spin_unlock(&dev->reclaim_lock);
277+
}
273278

274279
module_put(drv->driver.owner);
275280

@@ -468,6 +473,7 @@ int xenbus_probe_node(struct xen_bus_type *bus,
468473
goto fail;
469474

470475
dev_set_name(&xendev->dev, "%s", devname);
476+
spin_lock_init(&xendev->reclaim_lock);
471477

472478
/* Register with generic device framework. */
473479
err = device_register(&xendev->dev);

drivers/xen/xenbus/xenbus_probe_backend.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,12 +250,18 @@ static int backend_probe_and_watch(struct notifier_block *notifier,
250250
static int backend_reclaim_memory(struct device *dev, void *data)
251251
{
252252
const struct xenbus_driver *drv;
253+
struct xenbus_device *xdev;
253254

254255
if (!dev->driver)
255256
return 0;
256257
drv = to_xenbus_driver(dev->driver);
257-
if (drv && drv->reclaim_memory)
258-
drv->reclaim_memory(to_xenbus_device(dev));
258+
if (drv && drv->reclaim_memory) {
259+
xdev = to_xenbus_device(dev);
260+
if (!spin_trylock(&xdev->reclaim_lock))
261+
return 0;
262+
drv->reclaim_memory(xdev);
263+
spin_unlock(&xdev->reclaim_lock);
264+
}
259265
return 0;
260266
}
261267

include/xen/xenbus.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ struct xenbus_device {
7676
enum xenbus_state state;
7777
struct completion down;
7878
struct work_struct work;
79+
spinlock_t reclaim_lock;
7980
};
8081

8182
static inline struct xenbus_device *to_xenbus_device(struct device *dev)

0 commit comments

Comments
 (0)