A balloon enhancement, and a minor race-on-module-unload theoretical
bug which doesn't merit cc: stable. All the exciting stuff went via MST this cycle. Thanks, Rusty. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJUkPhtAAoJENkgDmzRrbjxnEoP/iXZ2d0pwbSQSSw12wXec7BO aT698KzTHg2naRqWEhRbE5ujGW9ZR1hbkH3r70R2BlM5wZTwCAEkJB4SRfIu6u0R fv9GUgZTdSIlN2+yBW1eYHa2QlB8V/jx3P2Vyw3/ejGQ2vC6B7JbNsdCZJoyuH5A jZojZUrltfEdPVO4JkZ9sSzo64fzyoHGj8YYilH8ygcyZOshAvKvP/gOsFyRzyaj OPCU1CImBj5i1w2dFSErhKPJp/WQl7La1dKwTVE4lEGKadKDmqnStV0JKuvcRPv6 XB/9vwdRXtFIxRUKDH8Wj7DrkKRCsBh6DJUl+MC+c2TVLNu6v0D/WGOlmio2rvoZ 6CGwNBQg4Ex/J8CkcYsgISn/jzDS+0oaZK0P+IYNJtv5e7D6jPJcDoZ1yPXh1uPn 9ZYZlKa08o5/991f3HM2kJKWDP/OdzgHQH6w2exY01Zsz/6TATLvU7xoPQuHelWe mRd1kbW4ONIUAzIGPhd5PvtnmJ2L82+tN3VmYu50XAl2oSF8fzvQ/VHl9hgyu/vI WREA7/40e2DYkhRbu7focdEAFYo0HnuRq6Kwp5zYjbfgyBsiaY7DVvAUlnhwhMES kSFKejGUP00gofrXdffTYNu5LdKMN8eaVT7pMyxNXlQHSzXe3Vc6oqnpXzP17ii7 ahqmeDZKNUF3GSOHc4IC =COY0 -----END PGP SIGNATURE----- Merge tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux Pull virtio updates from Rusty Russell: "A balloon enhancement, and a minor race-on-module-unload theoretical bug which doesn't merit cc: stable. All the exciting stuff went via MST this cycle" * tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux: virtio_balloon: free some memory from balloon on OOM virtio_balloon: return the amount of freed memory from leak_balloon() virtio_blk: fix race at module removal virtio: Fix comment typo 'CONFIG_S_FAILED'
This commit is contained in:
commit
9f3e151299
3 changed files with 58 additions and 2 deletions
|
@ -28,6 +28,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/balloon_compaction.h>
|
||||
#include <linux/oom.h>
|
||||
|
||||
/*
|
||||
* Balloon device works in 4K page units. So each page is pointed to by
|
||||
|
@ -36,6 +37,12 @@
|
|||
*/
|
||||
#define VIRTIO_BALLOON_PAGES_PER_PAGE (unsigned)(PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT)
|
||||
#define VIRTIO_BALLOON_ARRAY_PFNS_MAX 256
|
||||
#define OOM_VBALLOON_DEFAULT_PAGES 256
|
||||
#define VIRTBALLOON_OOM_NOTIFY_PRIORITY 80
|
||||
|
||||
static int oom_pages = OOM_VBALLOON_DEFAULT_PAGES;
|
||||
module_param(oom_pages, int, S_IRUSR | S_IWUSR);
|
||||
MODULE_PARM_DESC(oom_pages, "pages to free on OOM");
|
||||
|
||||
struct virtio_balloon
|
||||
{
|
||||
|
@ -71,6 +78,9 @@ struct virtio_balloon
|
|||
/* Memory statistics */
|
||||
int need_stats_update;
|
||||
struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR];
|
||||
|
||||
/* To register callback in oom notifier call chain */
|
||||
struct notifier_block nb;
|
||||
};
|
||||
|
||||
static struct virtio_device_id id_table[] = {
|
||||
|
@ -168,8 +178,9 @@ static void release_pages_by_pfn(const u32 pfns[], unsigned int num)
|
|||
}
|
||||
}
|
||||
|
||||
static void leak_balloon(struct virtio_balloon *vb, size_t num)
|
||||
static unsigned leak_balloon(struct virtio_balloon *vb, size_t num)
|
||||
{
|
||||
unsigned num_freed_pages;
|
||||
struct page *page;
|
||||
struct balloon_dev_info *vb_dev_info = &vb->vb_dev_info;
|
||||
|
||||
|
@ -186,6 +197,7 @@ static void leak_balloon(struct virtio_balloon *vb, size_t num)
|
|||
vb->num_pages -= VIRTIO_BALLOON_PAGES_PER_PAGE;
|
||||
}
|
||||
|
||||
num_freed_pages = vb->num_pfns;
|
||||
/*
|
||||
* Note that if
|
||||
* virtio_has_feature(vdev, VIRTIO_BALLOON_F_MUST_TELL_HOST);
|
||||
|
@ -195,6 +207,7 @@ static void leak_balloon(struct virtio_balloon *vb, size_t num)
|
|||
tell_host(vb, vb->deflate_vq);
|
||||
mutex_unlock(&vb->balloon_lock);
|
||||
release_pages_by_pfn(vb->pfns, vb->num_pfns);
|
||||
return num_freed_pages;
|
||||
}
|
||||
|
||||
static inline void update_stat(struct virtio_balloon *vb, int idx,
|
||||
|
@ -287,6 +300,38 @@ static void update_balloon_size(struct virtio_balloon *vb)
|
|||
&actual);
|
||||
}
|
||||
|
||||
/*
|
||||
* virtballoon_oom_notify - release pages when system is under severe
|
||||
* memory pressure (called from out_of_memory())
|
||||
* @self : notifier block struct
|
||||
* @dummy: not used
|
||||
* @parm : returned - number of freed pages
|
||||
*
|
||||
* The balancing of memory by use of the virtio balloon should not cause
|
||||
* the termination of processes while there are pages in the balloon.
|
||||
* If virtio balloon manages to release some memory, it will make the
|
||||
* system return and retry the allocation that forced the OOM killer
|
||||
* to run.
|
||||
*/
|
||||
static int virtballoon_oom_notify(struct notifier_block *self,
|
||||
unsigned long dummy, void *parm)
|
||||
{
|
||||
struct virtio_balloon *vb;
|
||||
unsigned long *freed;
|
||||
unsigned num_freed_pages;
|
||||
|
||||
vb = container_of(self, struct virtio_balloon, nb);
|
||||
if (!virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM))
|
||||
return NOTIFY_OK;
|
||||
|
||||
freed = parm;
|
||||
num_freed_pages = leak_balloon(vb, oom_pages);
|
||||
update_balloon_size(vb);
|
||||
*freed += num_freed_pages;
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static int balloon(void *_vballoon)
|
||||
{
|
||||
struct virtio_balloon *vb = _vballoon;
|
||||
|
@ -443,6 +488,12 @@ static int virtballoon_probe(struct virtio_device *vdev)
|
|||
if (err)
|
||||
goto out_free_vb;
|
||||
|
||||
vb->nb.notifier_call = virtballoon_oom_notify;
|
||||
vb->nb.priority = VIRTBALLOON_OOM_NOTIFY_PRIORITY;
|
||||
err = register_oom_notifier(&vb->nb);
|
||||
if (err < 0)
|
||||
goto out_oom_notify;
|
||||
|
||||
vb->thread = kthread_run(balloon, vb, "vballoon");
|
||||
if (IS_ERR(vb->thread)) {
|
||||
err = PTR_ERR(vb->thread);
|
||||
|
@ -452,6 +503,8 @@ static int virtballoon_probe(struct virtio_device *vdev)
|
|||
return 0;
|
||||
|
||||
out_del_vqs:
|
||||
unregister_oom_notifier(&vb->nb);
|
||||
out_oom_notify:
|
||||
vdev->config->del_vqs(vdev);
|
||||
out_free_vb:
|
||||
kfree(vb);
|
||||
|
@ -476,6 +529,7 @@ static void virtballoon_remove(struct virtio_device *vdev)
|
|||
{
|
||||
struct virtio_balloon *vb = vdev->priv;
|
||||
|
||||
unregister_oom_notifier(&vb->nb);
|
||||
kthread_stop(vb->thread);
|
||||
remove_common(vb);
|
||||
kfree(vb);
|
||||
|
@ -515,6 +569,7 @@ static int virtballoon_restore(struct virtio_device *vdev)
|
|||
static unsigned int features[] = {
|
||||
VIRTIO_BALLOON_F_MUST_TELL_HOST,
|
||||
VIRTIO_BALLOON_F_STATS_VQ,
|
||||
VIRTIO_BALLOON_F_DEFLATE_ON_OOM,
|
||||
};
|
||||
|
||||
static struct virtio_driver virtio_balloon_driver = {
|
||||
|
|
|
@ -81,7 +81,7 @@ void *virtqueue_get_used(struct virtqueue *vq);
|
|||
/**
|
||||
* virtio_device - representation of a device using virtio
|
||||
* @index: unique position on the virtio bus
|
||||
* @failed: saved value for CONFIG_S_FAILED bit (for restore)
|
||||
* @failed: saved value for VIRTIO_CONFIG_S_FAILED bit (for restore)
|
||||
* @config_enabled: configuration change reporting enabled
|
||||
* @config_change_pending: configuration change reported while disabled
|
||||
* @config_lock: protects configuration change reporting
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
/* The feature bitmap for virtio balloon */
|
||||
#define VIRTIO_BALLOON_F_MUST_TELL_HOST 0 /* Tell before reclaiming pages */
|
||||
#define VIRTIO_BALLOON_F_STATS_VQ 1 /* Memory Stats virtqueue */
|
||||
#define VIRTIO_BALLOON_F_DEFLATE_ON_OOM 2 /* Deflate balloon on OOM */
|
||||
|
||||
/* Size of a PFN in the balloon interface. */
|
||||
#define VIRTIO_BALLOON_PFN_SHIFT 12
|
||||
|
|
Loading…
Reference in a new issue