| .. | .. |
|---|
| 45 | 45 | #include <linux/mm.h> |
|---|
| 46 | 46 | #include <linux/notifier.h> |
|---|
| 47 | 47 | #include <linux/export.h> |
|---|
| 48 | +#include <linux/semaphore.h> |
|---|
| 48 | 49 | |
|---|
| 49 | 50 | #include <asm/page.h> |
|---|
| 50 | | -#include <asm/pgtable.h> |
|---|
| 51 | 51 | #include <asm/xen/hypervisor.h> |
|---|
| 52 | 52 | #include <asm/hypervisor.h> |
|---|
| 53 | 53 | #include <xen/xenbus.h> |
|---|
| .. | .. |
|---|
| 205 | 205 | .uevent = xenbus_uevent_backend, |
|---|
| 206 | 206 | .probe = xenbus_dev_probe, |
|---|
| 207 | 207 | .remove = xenbus_dev_remove, |
|---|
| 208 | | - .shutdown = xenbus_dev_shutdown, |
|---|
| 209 | 208 | .dev_groups = xenbus_dev_groups, |
|---|
| 210 | 209 | }, |
|---|
| 211 | 210 | }; |
|---|
| .. | .. |
|---|
| 255 | 254 | return NOTIFY_DONE; |
|---|
| 256 | 255 | } |
|---|
| 257 | 256 | |
|---|
| 257 | +static int backend_reclaim_memory(struct device *dev, void *data) |
|---|
| 258 | +{ |
|---|
| 259 | + const struct xenbus_driver *drv; |
|---|
| 260 | + struct xenbus_device *xdev; |
|---|
| 261 | + |
|---|
| 262 | + if (!dev->driver) |
|---|
| 263 | + return 0; |
|---|
| 264 | + drv = to_xenbus_driver(dev->driver); |
|---|
| 265 | + if (drv && drv->reclaim_memory) { |
|---|
| 266 | + xdev = to_xenbus_device(dev); |
|---|
| 267 | + if (down_trylock(&xdev->reclaim_sem)) |
|---|
| 268 | + return 0; |
|---|
| 269 | + drv->reclaim_memory(xdev); |
|---|
| 270 | + up(&xdev->reclaim_sem); |
|---|
| 271 | + } |
|---|
| 272 | + return 0; |
|---|
| 273 | +} |
|---|
| 274 | + |
|---|
| 275 | +/* |
|---|
| 276 | + * Returns 0 always because we are using shrinker to only detect memory |
|---|
| 277 | + * pressure. |
|---|
| 278 | + */ |
|---|
| 279 | +static unsigned long backend_shrink_memory_count(struct shrinker *shrinker, |
|---|
| 280 | + struct shrink_control *sc) |
|---|
| 281 | +{ |
|---|
| 282 | + bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, |
|---|
| 283 | + backend_reclaim_memory); |
|---|
| 284 | + return 0; |
|---|
| 285 | +} |
|---|
| 286 | + |
|---|
| 287 | +static struct shrinker backend_memory_shrinker = { |
|---|
| 288 | + .count_objects = backend_shrink_memory_count, |
|---|
| 289 | + .seeks = DEFAULT_SEEKS, |
|---|
| 290 | +}; |
|---|
| 291 | + |
|---|
| 258 | 292 | static int __init xenbus_probe_backend_init(void) |
|---|
| 259 | 293 | { |
|---|
| 260 | 294 | static struct notifier_block xenstore_notifier = { |
|---|
| .. | .. |
|---|
| 271 | 305 | |
|---|
| 272 | 306 | register_xenstore_notifier(&xenstore_notifier); |
|---|
| 273 | 307 | |
|---|
| 308 | + if (register_shrinker(&backend_memory_shrinker)) |
|---|
| 309 | + pr_warn("shrinker registration failed\n"); |
|---|
| 310 | + |
|---|
| 274 | 311 | return 0; |
|---|
| 275 | 312 | } |
|---|
| 276 | 313 | subsys_initcall(xenbus_probe_backend_init); |
|---|