Skip to content

Commit c7cdff0

Browse files
committed
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>
1 parent bebc608 commit c7cdff0

File tree

3 files changed

+74
-13
lines changed

3 files changed

+74
-13
lines changed

drivers/virtio/virtio_balloon.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,16 +143,17 @@ static void set_page_pfns(struct virtio_balloon *vb,
143143

144144
static unsigned fill_balloon(struct virtio_balloon *vb, size_t num)
145145
{
146-
struct balloon_dev_info *vb_dev_info = &vb->vb_dev_info;
147146
unsigned num_allocated_pages;
147+
unsigned num_pfns;
148+
struct page *page;
149+
LIST_HEAD(pages);
148150

149151
/* We can only do one array worth at a time. */
150152
num = min(num, ARRAY_SIZE(vb->pfns));
151153

152-
mutex_lock(&vb->balloon_lock);
153-
for (vb->num_pfns = 0; vb->num_pfns < num;
154-
vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
155-
struct page *page = balloon_page_enqueue(vb_dev_info);
154+
for (num_pfns = 0; num_pfns < num;
155+
num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
156+
struct page *page = balloon_page_alloc();
156157

157158
if (!page) {
158159
dev_info_ratelimited(&vb->vdev->dev,
@@ -162,6 +163,19 @@ static unsigned fill_balloon(struct virtio_balloon *vb, size_t num)
162163
msleep(200);
163164
break;
164165
}
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+
165179
set_page_pfns(vb, vb->pfns + vb->num_pfns, page);
166180
vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE;
167181
if (!virtio_has_feature(vb->vdev,

include/linux/balloon_compaction.h

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include <linux/gfp.h>
5151
#include <linux/err.h>
5252
#include <linux/fs.h>
53+
#include <linux/list.h>
5354

5455
/*
5556
* Balloon device information descriptor.
@@ -67,7 +68,9 @@ struct balloon_dev_info {
6768
struct inode *inode;
6869
};
6970

70-
extern struct page *balloon_page_enqueue(struct balloon_dev_info *b_dev_info);
71+
extern struct page *balloon_page_alloc(void);
72+
extern void balloon_page_enqueue(struct balloon_dev_info *b_dev_info,
73+
struct page *page);
7174
extern struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info);
7275

7376
static inline void balloon_devinfo_init(struct balloon_dev_info *balloon)
@@ -193,4 +196,34 @@ static inline gfp_t balloon_mapping_gfp_mask(void)
193196
}
194197

195198
#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+
*/
207+
static 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+
*/
219+
static 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+
}
196229
#endif /* _LINUX_BALLOON_COMPACTION_H */

mm/balloon_compaction.c

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,38 @@
1010
#include <linux/export.h>
1111
#include <linux/balloon_compaction.h>
1212

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+
*/
22+
struct 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+
}
28+
EXPORT_SYMBOL_GPL(balloon_page_alloc);
29+
1330
/*
1431
* balloon_page_enqueue - allocates a new page and inserts it into the balloon
1532
* page list.
1633
* @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.
1735
*
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
1937
* before definitively removing it from the guest system.
2038
* This function returns the page address for the recently enqueued page or
2139
* NULL in the case we fail to allocate a new page this turn.
2240
*/
23-
struct page *balloon_page_enqueue(struct balloon_dev_info *b_dev_info)
41+
void balloon_page_enqueue(struct balloon_dev_info *b_dev_info,
42+
struct page *page)
2443
{
2544
unsigned long flags;
26-
struct page *page = alloc_page(balloon_mapping_gfp_mask() |
27-
__GFP_NOMEMALLOC | __GFP_NORETRY);
28-
if (!page)
29-
return NULL;
3045

3146
/*
3247
* 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)
3954
__count_vm_event(BALLOON_INFLATE);
4055
spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
4156
unlock_page(page);
42-
return page;
4357
}
4458
EXPORT_SYMBOL_GPL(balloon_page_enqueue);
4559

0 commit comments

Comments
 (0)