Skip to content

Commit 8fa3c61

Browse files
anadavgregkh
authored andcommitted
vmw_balloon: treat all refused pages equally
Currently, when the hypervisor rejects a page during lock operation, the VM treats pages differently according to the error-code: in certain cases the page is immediately freed, and in others it is put on a rejection list and only freed later. The behavior does not make too much sense. If the page is freed immediately it is very likely to be used again in the next batch of allocations, and be rejected again. In addition, for support of compaction and OOM notifiers, we wish to separate the logic that communicates with the hypervisor (as well as analyzes the status of each page) from the logic that allocates or free pages. Treat all errors the same way, queuing the pages on the refuse list. Move to the next allocation size (4k) when too many pages are refused. Free the refused pages when moving to the next size to avoid situations in which too much memory is waiting to be freed on the refused list. Reviewed-by: Xavier Deguillard <[email protected]> Signed-off-by: Nadav Amit <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent df8d0d4 commit 8fa3c61

File tree

1 file changed

+29
-23
lines changed

1 file changed

+29
-23
lines changed

drivers/misc/vmw_balloon.c

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -543,29 +543,13 @@ static int vmballoon_lock(struct vmballoon *b, unsigned int num_pages,
543543
/* Error occurred */
544544
STATS_INC(b->stats.refused_alloc[is_2m_pages]);
545545

546-
switch (status) {
547-
case VMW_BALLOON_ERROR_PPN_PINNED:
548-
case VMW_BALLOON_ERROR_PPN_INVALID:
549-
/*
550-
* Place page on the list of non-balloonable pages
551-
* and retry allocation, unless we already accumulated
552-
* too many of them, in which case take a breather.
553-
*/
554-
if (page_size->n_refused_pages
555-
< VMW_BALLOON_MAX_REFUSED) {
556-
list_add(&p->lru, &page_size->refused_pages);
557-
page_size->n_refused_pages++;
558-
break;
559-
}
560-
/* Fallthrough */
561-
case VMW_BALLOON_ERROR_RESET:
562-
case VMW_BALLOON_ERROR_PPN_NOTNEEDED:
563-
vmballoon_free_page(p, is_2m_pages);
564-
break;
565-
default:
566-
/* This should never happen */
567-
WARN_ON_ONCE(true);
568-
}
546+
/*
547+
* Place page on the list of non-balloonable pages
548+
* and retry allocation, unless we already accumulated
549+
* too many of them, in which case take a breather.
550+
*/
551+
list_add(&p->lru, &page_size->refused_pages);
552+
page_size->n_refused_pages++;
569553
}
570554

571555
return batch_status == VMW_BALLOON_SUCCESS ? 0 : -EIO;
@@ -712,9 +696,31 @@ static void vmballoon_inflate(struct vmballoon *b)
712696

713697
vmballoon_add_page(b, num_pages++, page);
714698
if (num_pages == b->batch_max_pages) {
699+
struct vmballoon_page_size *page_size =
700+
&b->page_sizes[is_2m_pages];
701+
715702
error = vmballoon_lock(b, num_pages, is_2m_pages);
716703

717704
num_pages = 0;
705+
706+
/*
707+
* Stop allocating this page size if we already
708+
* accumulated too many pages that the hypervisor
709+
* refused.
710+
*/
711+
if (page_size->n_refused_pages >=
712+
VMW_BALLOON_MAX_REFUSED) {
713+
if (!is_2m_pages)
714+
break;
715+
716+
/*
717+
* Release the refused pages as we move to 4k
718+
* pages.
719+
*/
720+
vmballoon_release_refused_pages(b, true);
721+
is_2m_pages = true;
722+
}
723+
718724
if (error)
719725
break;
720726
}

0 commit comments

Comments
 (0)