aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2017-10-13 09:11:48 -0400
committerMichael S. Tsirkin <mst@redhat.com>2017-11-14 16:57:38 -0500
commitc7cdff0e864713a089d7cb3a2b1136ba9a54881a (patch)
tree10844edfefa9cf4b619bbbd5722404acb858eefd
parentbebc6082da0a9f5d47a1ea2edc099bf671058bd4 (diff)
virtio_balloon: fix deadlock on OOM
fill_balloon doing memory allocations under balloon_lock can cause a deadlock when leak_balloon is called from virtballoon_oom_notify and tries to take same lock. To fix, split page allocation and enqueue and do allocations outside the lock. Here's a detailed analysis of the deadlock by Tetsuo Handa: In leak_balloon(), mutex_lock(&vb->balloon_lock) is called in order to serialize against fill_balloon(). But in fill_balloon(), alloc_page(GFP_HIGHUSER[_MOVABLE] | __GFP_NOMEMALLOC | __GFP_NORETRY) is called with vb->balloon_lock mutex held. Since GFP_HIGHUSER[_MOVABLE] implies __GFP_DIRECT_RECLAIM | __GFP_IO | __GFP_FS, despite __GFP_NORETRY is specified, this allocation attempt might indirectly depend on somebody else's __GFP_DIRECT_RECLAIM memory allocation. And such indirect __GFP_DIRECT_RECLAIM memory allocation might call leak_balloon() via virtballoon_oom_notify() via blocking_notifier_call_chain() callback via out_of_memory() when it reached __alloc_pages_may_oom() and held oom_lock mutex. Since vb->balloon_lock mutex is already held by fill_balloon(), it will cause OOM lockup. Thread1 Thread2 fill_balloon() takes a balloon_lock balloon_page_enqueue() alloc_page(GFP_HIGHUSER_MOVABLE) direct reclaim (__GFP_FS context) takes a fs lock waits for that fs lock alloc_page(GFP_NOFS) __alloc_pages_may_oom() takes the oom_lock out_of_memory() blocking_notifier_call_chain() leak_balloon() tries to take that balloon_lock and deadlocks Reported-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Cc: Michal Hocko <mhocko@suse.com> Cc: Wei Wang <wei.w.wang@intel.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-rw-r--r--drivers/virtio/virtio_balloon.c24
-rw-r--r--include/linux/balloon_compaction.h35
-rw-r--r--mm/balloon_compaction.c28
3 files changed, 74 insertions, 13 deletions
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index f0b3a0b9d42f..7960746f7597 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -143,16 +143,17 @@ static void set_page_pfns(struct virtio_balloon *vb,
143 143
144static unsigned fill_balloon(struct virtio_balloon *vb, size_t num) 144static unsigned fill_balloon(struct virtio_balloon *vb, size_t num)
145{ 145{
146 struct balloon_dev_info *vb_dev_info = &vb->vb_dev_info;
147 unsigned num_allocated_pages; 146 unsigned num_allocated_pages;
147 unsigned num_pfns;
148 struct page *page;
149 LIST_HEAD(pages);
148 150
149 /* We can only do one array worth at a time. */ 151 /* We can only do one array worth at a time. */
150 num = min(num, ARRAY_SIZE(vb->pfns)); 152 num = min(num, ARRAY_SIZE(vb->pfns));
151 153
152 mutex_lock(&vb->balloon_lock); 154 for (num_pfns = 0; num_pfns < num;
153 for (vb->num_pfns = 0; vb->num_pfns < num; 155 num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
154 vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) { 156 struct page *page = balloon_page_alloc();
155 struct page *page = balloon_page_enqueue(vb_dev_info);
156 157
157 if (!page) { 158 if (!page) {
158 dev_info_ratelimited(&vb->vdev->dev, 159 dev_info_ratelimited(&vb->vdev->dev,
@@ -162,6 +163,19 @@ static unsigned fill_balloon(struct virtio_balloon *vb, size_t num)
162 msleep(200); 163 msleep(200);
163 break; 164 break;
164 } 165 }
166
167 balloon_page_push(&pages, page);
168 }
169
170 mutex_lock(&vb->balloon_lock);
171
172 vb->num_pfns = 0;
173
174 while ((page = balloon_page_pop(&pages))) {
175 balloon_page_enqueue(&vb->vb_dev_info, page);
176
177 vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE;
178
165 set_page_pfns(vb, vb->pfns + vb->num_pfns, page); 179 set_page_pfns(vb, vb->pfns + vb->num_pfns, page);
166 vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE; 180 vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE;
167 if (!virtio_has_feature(vb->vdev, 181 if (!virtio_has_feature(vb->vdev,
diff --git a/include/linux/balloon_compaction.h b/include/linux/balloon_compaction.h
index fbbe6da40fed..53051f3d8f25 100644
--- a/include/linux/balloon_compaction.h
+++ b/include/linux/balloon_compaction.h
@@ -50,6 +50,7 @@
50#include <linux/gfp.h> 50#include <linux/gfp.h>
51#include <linux/err.h> 51#include <linux/err.h>
52#include <linux/fs.h> 52#include <linux/fs.h>
53#include <linux/list.h>
53 54
54/* 55/*
55 * Balloon device information descriptor. 56 * Balloon device information descriptor.
@@ -67,7 +68,9 @@ struct balloon_dev_info {
67 struct inode *inode; 68 struct inode *inode;
68}; 69};
69 70
70extern struct page *balloon_page_enqueue(struct balloon_dev_info *b_dev_info); 71extern struct page *balloon_page_alloc(void);
72extern void balloon_page_enqueue(struct balloon_dev_info *b_dev_info,
73 struct page *page);
71extern struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info); 74extern struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info);
72 75
73static inline void balloon_devinfo_init(struct balloon_dev_info *balloon) 76static inline void balloon_devinfo_init(struct balloon_dev_info *balloon)
@@ -193,4 +196,34 @@ static inline gfp_t balloon_mapping_gfp_mask(void)
193} 196}
194 197
195#endif /* CONFIG_BALLOON_COMPACTION */ 198#endif /* CONFIG_BALLOON_COMPACTION */
199
200/*
201 * balloon_page_push - insert a page into a page list.
202 * @head : pointer to list
203 * @page : page to be added
204 *
205 * Caller must ensure the page is private and protect the list.
206 */
207static inline void balloon_page_push(struct list_head *pages, struct page *page)
208{
209 list_add(&page->lru, pages);
210}
211
212/*
213 * balloon_page_pop - remove a page from a page list.
214 * @head : pointer to list
215 * @page : page to be added
216 *
217 * Caller must ensure the page is private and protect the list.
218 */
219static inline struct page *balloon_page_pop(struct list_head *pages)
220{
221 struct page *page = list_first_entry_or_null(pages, struct page, lru);
222
223 if (!page)
224 return NULL;
225
226 list_del(&page->lru);
227 return page;
228}
196#endif /* _LINUX_BALLOON_COMPACTION_H */ 229#endif /* _LINUX_BALLOON_COMPACTION_H */
diff --git a/mm/balloon_compaction.c b/mm/balloon_compaction.c
index 68d28924ba79..ef858d547e2d 100644
--- a/mm/balloon_compaction.c
+++ b/mm/balloon_compaction.c
@@ -11,22 +11,37 @@
11#include <linux/balloon_compaction.h> 11#include <linux/balloon_compaction.h>
12 12
13/* 13/*
14 * balloon_page_alloc - allocates a new page for insertion into the balloon
15 * page list.
16 *
17 * Driver must call it to properly allocate a new enlisted balloon page.
18 * Driver must call balloon_page_enqueue before definitively removing it from
19 * the guest system. This function returns the page address for the recently
20 * allocated page or NULL in the case we fail to allocate a new page this turn.
21 */
22struct page *balloon_page_alloc(void)
23{
24 struct page *page = alloc_page(balloon_mapping_gfp_mask() |
25 __GFP_NOMEMALLOC | __GFP_NORETRY);
26 return page;
27}
28EXPORT_SYMBOL_GPL(balloon_page_alloc);
29
30/*
14 * balloon_page_enqueue - allocates a new page and inserts it into the balloon 31 * balloon_page_enqueue - allocates a new page and inserts it into the balloon
15 * page list. 32 * page list.
16 * @b_dev_info: balloon device descriptor where we will insert a new page to 33 * @b_dev_info: balloon device descriptor where we will insert a new page to
34 * @page: new page to enqueue - allocated using balloon_page_alloc.
17 * 35 *
18 * Driver must call it to properly allocate a new enlisted balloon page 36 * Driver must call it to properly enqueue a new allocated balloon page
19 * before definitively removing it from the guest system. 37 * before definitively removing it from the guest system.
20 * This function returns the page address for the recently enqueued page or 38 * This function returns the page address for the recently enqueued page or
21 * NULL in the case we fail to allocate a new page this turn. 39 * NULL in the case we fail to allocate a new page this turn.
22 */ 40 */
23struct page *balloon_page_enqueue(struct balloon_dev_info *b_dev_info) 41void balloon_page_enqueue(struct balloon_dev_info *b_dev_info,
42 struct page *page)
24{ 43{
25 unsigned long flags; 44 unsigned long flags;
26 struct page *page = alloc_page(balloon_mapping_gfp_mask() |
27 __GFP_NOMEMALLOC | __GFP_NORETRY);
28 if (!page)
29 return NULL;
30 45
31 /* 46 /*
32 * Block others from accessing the 'page' when we get around to 47 * Block others from accessing the 'page' when we get around to
@@ -39,7 +54,6 @@ struct page *balloon_page_enqueue(struct balloon_dev_info *b_dev_info)
39 __count_vm_event(BALLOON_INFLATE); 54 __count_vm_event(BALLOON_INFLATE);
40 spin_unlock_irqrestore(&b_dev_info->pages_lock, flags); 55 spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
41 unlock_page(page); 56 unlock_page(page);
42 return page;
43} 57}
44EXPORT_SYMBOL_GPL(balloon_page_enqueue); 58EXPORT_SYMBOL_GPL(balloon_page_enqueue);
45 59