Commit 9f3e1512 authored by Linus Torvalds's avatar Linus Torvalds

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'
parents 2efda904 5a10b7db
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/balloon_compaction.h> #include <linux/balloon_compaction.h>
#include <linux/oom.h>
/* /*
* Balloon device works in 4K page units. So each page is pointed to by * Balloon device works in 4K page units. So each page is pointed to by
...@@ -36,6 +37,12 @@ ...@@ -36,6 +37,12 @@
*/ */
#define VIRTIO_BALLOON_PAGES_PER_PAGE (unsigned)(PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT) #define VIRTIO_BALLOON_PAGES_PER_PAGE (unsigned)(PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT)
#define VIRTIO_BALLOON_ARRAY_PFNS_MAX 256 #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 struct virtio_balloon
{ {
...@@ -71,6 +78,9 @@ struct virtio_balloon ...@@ -71,6 +78,9 @@ struct virtio_balloon
/* Memory statistics */ /* Memory statistics */
int need_stats_update; int need_stats_update;
struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR]; 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[] = { static struct virtio_device_id id_table[] = {
...@@ -168,8 +178,9 @@ static void release_pages_by_pfn(const u32 pfns[], unsigned int num) ...@@ -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 page *page;
struct balloon_dev_info *vb_dev_info = &vb->vb_dev_info; 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) ...@@ -186,6 +197,7 @@ static void leak_balloon(struct virtio_balloon *vb, size_t num)
vb->num_pages -= VIRTIO_BALLOON_PAGES_PER_PAGE; vb->num_pages -= VIRTIO_BALLOON_PAGES_PER_PAGE;
} }
num_freed_pages = vb->num_pfns;
/* /*
* Note that if * Note that if
* virtio_has_feature(vdev, VIRTIO_BALLOON_F_MUST_TELL_HOST); * 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) ...@@ -195,6 +207,7 @@ static void leak_balloon(struct virtio_balloon *vb, size_t num)
tell_host(vb, vb->deflate_vq); tell_host(vb, vb->deflate_vq);
mutex_unlock(&vb->balloon_lock); mutex_unlock(&vb->balloon_lock);
release_pages_by_pfn(vb->pfns, vb->num_pfns); release_pages_by_pfn(vb->pfns, vb->num_pfns);
return num_freed_pages;
} }
static inline void update_stat(struct virtio_balloon *vb, int idx, static inline void update_stat(struct virtio_balloon *vb, int idx,
...@@ -287,6 +300,38 @@ static void update_balloon_size(struct virtio_balloon *vb) ...@@ -287,6 +300,38 @@ static void update_balloon_size(struct virtio_balloon *vb)
&actual); &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) static int balloon(void *_vballoon)
{ {
struct virtio_balloon *vb = _vballoon; struct virtio_balloon *vb = _vballoon;
...@@ -443,6 +488,12 @@ static int virtballoon_probe(struct virtio_device *vdev) ...@@ -443,6 +488,12 @@ static int virtballoon_probe(struct virtio_device *vdev)
if (err) if (err)
goto out_free_vb; 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"); vb->thread = kthread_run(balloon, vb, "vballoon");
if (IS_ERR(vb->thread)) { if (IS_ERR(vb->thread)) {
err = PTR_ERR(vb->thread); err = PTR_ERR(vb->thread);
...@@ -452,6 +503,8 @@ static int virtballoon_probe(struct virtio_device *vdev) ...@@ -452,6 +503,8 @@ static int virtballoon_probe(struct virtio_device *vdev)
return 0; return 0;
out_del_vqs: out_del_vqs:
unregister_oom_notifier(&vb->nb);
out_oom_notify:
vdev->config->del_vqs(vdev); vdev->config->del_vqs(vdev);
out_free_vb: out_free_vb:
kfree(vb); kfree(vb);
...@@ -476,6 +529,7 @@ static void virtballoon_remove(struct virtio_device *vdev) ...@@ -476,6 +529,7 @@ static void virtballoon_remove(struct virtio_device *vdev)
{ {
struct virtio_balloon *vb = vdev->priv; struct virtio_balloon *vb = vdev->priv;
unregister_oom_notifier(&vb->nb);
kthread_stop(vb->thread); kthread_stop(vb->thread);
remove_common(vb); remove_common(vb);
kfree(vb); kfree(vb);
...@@ -515,6 +569,7 @@ static int virtballoon_restore(struct virtio_device *vdev) ...@@ -515,6 +569,7 @@ static int virtballoon_restore(struct virtio_device *vdev)
static unsigned int features[] = { static unsigned int features[] = {
VIRTIO_BALLOON_F_MUST_TELL_HOST, VIRTIO_BALLOON_F_MUST_TELL_HOST,
VIRTIO_BALLOON_F_STATS_VQ, VIRTIO_BALLOON_F_STATS_VQ,
VIRTIO_BALLOON_F_DEFLATE_ON_OOM,
}; };
static struct virtio_driver virtio_balloon_driver = { static struct virtio_driver virtio_balloon_driver = {
......
...@@ -81,7 +81,7 @@ void *virtqueue_get_used(struct virtqueue *vq); ...@@ -81,7 +81,7 @@ void *virtqueue_get_used(struct virtqueue *vq);
/** /**
* virtio_device - representation of a device using virtio * virtio_device - representation of a device using virtio
* @index: unique position on the virtio bus * @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_enabled: configuration change reporting enabled
* @config_change_pending: configuration change reported while disabled * @config_change_pending: configuration change reported while disabled
* @config_lock: protects configuration change reporting * @config_lock: protects configuration change reporting
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
/* The feature bitmap for virtio balloon */ /* The feature bitmap for virtio balloon */
#define VIRTIO_BALLOON_F_MUST_TELL_HOST 0 /* Tell before reclaiming pages */ #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_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. */ /* Size of a PFN in the balloon interface. */
#define VIRTIO_BALLOON_PFN_SHIFT 12 #define VIRTIO_BALLOON_PFN_SHIFT 12
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment