Skip to content

Commit 33d268e

Browse files
Philip P. Moltmanngregkh
authored andcommitted
VMware balloon: Do not limit the amount of frees and allocations in non-sleep mode.
When VMware's hypervisor requests a VM to reclaim memory this is preferrably done via ballooning. If the balloon driver does not return memory fast enough, more drastic methods, such as hypervisor-level swapping are needed. These other methods cause performance issues, e.g. hypervisor-level swapping requires the hypervisor to swap in a page syncronously while the virtual CPU is blocked. Hence it is in the interest of the VM to balloon memory as fast as possible. The problem with doing this is that the VM might end up doing nothing else than ballooning and the user might notice that the VM is stalled, esp. when the VM has only a single virtual CPU. This is less of a problem if the VM and the hypervisor perform balloon operations faster. Also the balloon driver yields regularly, hence on a single virtual CPU the Linux scheduler should be able to properly time-slice between ballooning and other tasks. Testing Done: quickly ballooned a lot of pages while wathing if there are any perceived hickups (periods of non-responsiveness) in the execution of the linux VM. No such hickups were seen. Signed-off-by: Xavier Deguillard <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent b36e89d commit 33d268e

File tree

1 file changed

+16
-52
lines changed

1 file changed

+16
-52
lines changed

drivers/misc/vmw_balloon.c

Lines changed: 16 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747

4848
MODULE_AUTHOR("VMware, Inc.");
4949
MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver");
50-
MODULE_VERSION("1.3.3.0-k");
50+
MODULE_VERSION("1.3.4.0-k");
5151
MODULE_ALIAS("dmi:*:svnVMware*:*");
5252
MODULE_ALIAS("vmware_vmmemctl");
5353
MODULE_LICENSE("GPL");
@@ -57,12 +57,6 @@ MODULE_LICENSE("GPL");
5757
* measured in pages.
5858
*/
5959

60-
/*
61-
* Rate of allocating memory when there is no memory pressure
62-
* (driver performs non-sleeping allocations).
63-
*/
64-
#define VMW_BALLOON_NOSLEEP_ALLOC_MAX 16384U
65-
6660
/*
6761
* Rates of memory allocaton when guest experiences memory pressure
6862
* (driver performs sleeping allocations).
@@ -71,13 +65,6 @@ MODULE_LICENSE("GPL");
7165
#define VMW_BALLOON_RATE_ALLOC_MAX 2048U
7266
#define VMW_BALLOON_RATE_ALLOC_INC 16U
7367

74-
/*
75-
* Rates for releasing pages while deflating balloon.
76-
*/
77-
#define VMW_BALLOON_RATE_FREE_MIN 512U
78-
#define VMW_BALLOON_RATE_FREE_MAX 16384U
79-
#define VMW_BALLOON_RATE_FREE_INC 16U
80-
8168
/*
8269
* When guest is under memory pressure, use a reduced page allocation
8370
* rate for next several cycles.
@@ -100,9 +87,6 @@ MODULE_LICENSE("GPL");
10087
*/
10188
#define VMW_PAGE_ALLOC_CANSLEEP (GFP_HIGHUSER)
10289

103-
/* Maximum number of page allocations without yielding processor */
104-
#define VMW_BALLOON_YIELD_THRESHOLD 1024
105-
10690
/* Maximum number of refused pages we accumulate during inflation cycle */
10791
#define VMW_BALLOON_MAX_REFUSED 16
10892

@@ -279,7 +263,6 @@ struct vmballoon {
279263

280264
/* adjustment rates (pages per second) */
281265
unsigned int rate_alloc;
282-
unsigned int rate_free;
283266

284267
/* slowdown page allocations for next few cycles */
285268
unsigned int slow_allocation_cycles;
@@ -503,18 +486,13 @@ static bool vmballoon_send_batched_unlock(struct vmballoon *b,
503486
static void vmballoon_pop(struct vmballoon *b)
504487
{
505488
struct page *page, *next;
506-
unsigned int count = 0;
507489

508490
list_for_each_entry_safe(page, next, &b->pages, lru) {
509491
list_del(&page->lru);
510492
__free_page(page);
511493
STATS_INC(b->stats.free);
512494
b->size--;
513-
514-
if (++count >= b->rate_free) {
515-
count = 0;
516-
cond_resched();
517-
}
495+
cond_resched();
518496
}
519497

520498
if ((b->capabilities & VMW_BALLOON_BATCHED_CMDS) != 0) {
@@ -716,7 +694,7 @@ static void vmballoon_add_batched_page(struct vmballoon *b, int idx,
716694
*/
717695
static void vmballoon_inflate(struct vmballoon *b)
718696
{
719-
unsigned int rate;
697+
unsigned rate;
720698
unsigned int allocations = 0;
721699
unsigned int num_pages = 0;
722700
int error = 0;
@@ -743,13 +721,13 @@ static void vmballoon_inflate(struct vmballoon *b)
743721
* Start with no sleep allocation rate which may be higher
744722
* than sleeping allocation rate.
745723
*/
746-
rate = b->slow_allocation_cycles ?
747-
b->rate_alloc : VMW_BALLOON_NOSLEEP_ALLOC_MAX;
724+
rate = b->slow_allocation_cycles ? b->rate_alloc : UINT_MAX;
748725

749-
pr_debug("%s - goal: %d, no-sleep rate: %d, sleep rate: %d\n",
726+
pr_debug("%s - goal: %d, no-sleep rate: %u, sleep rate: %d\n",
750727
__func__, b->target - b->size, rate, b->rate_alloc);
751728

752-
while (b->size < b->target && num_pages < b->target - b->size) {
729+
while (!b->reset_required &&
730+
b->size < b->target && num_pages < b->target - b->size) {
753731
struct page *page;
754732

755733
if (flags == VMW_PAGE_ALLOC_NOSLEEP)
@@ -799,10 +777,7 @@ static void vmballoon_inflate(struct vmballoon *b)
799777
break;
800778
}
801779

802-
if (++allocations > VMW_BALLOON_YIELD_THRESHOLD) {
803-
cond_resched();
804-
allocations = 0;
805-
}
780+
cond_resched();
806781

807782
if (allocations >= rate) {
808783
/* We allocated enough pages, let's take a break. */
@@ -838,36 +813,29 @@ static void vmballoon_deflate(struct vmballoon *b)
838813
unsigned int num_pages = 0;
839814
int error;
840815

841-
pr_debug("%s - size: %d, target %d, rate: %d\n", __func__, b->size,
842-
b->target, b->rate_free);
816+
pr_debug("%s - size: %d, target %d\n", __func__, b->size, b->target);
843817

844818
/* free pages to reach target */
845819
list_for_each_entry_safe(page, next, &b->pages, lru) {
846820
list_del(&page->lru);
847821
b->ops->add_page(b, num_pages++, page);
848822

823+
849824
if (num_pages == b->batch_max_pages) {
850825
error = b->ops->unlock(b, num_pages, &b->target);
851826
num_pages = 0;
852-
if (error) {
853-
/* quickly decrease rate in case of error */
854-
b->rate_free = max(b->rate_free / 2,
855-
VMW_BALLOON_RATE_FREE_MIN);
827+
if (error)
856828
return;
857-
}
858829
}
859830

860-
if (++i >= b->size - b->target)
831+
if (b->reset_required || ++i >= b->size - b->target)
861832
break;
833+
834+
cond_resched();
862835
}
863836

864837
if (num_pages > 0)
865838
b->ops->unlock(b, num_pages, &b->target);
866-
867-
/* slowly increase rate if there were no errors */
868-
if (error == 0)
869-
b->rate_free = min(b->rate_free + VMW_BALLOON_RATE_FREE_INC,
870-
VMW_BALLOON_RATE_FREE_MAX);
871839
}
872840

873841
static const struct vmballoon_ops vmballoon_basic_ops = {
@@ -993,11 +961,8 @@ static int vmballoon_debug_show(struct seq_file *f, void *offset)
993961

994962
/* format rate info */
995963
seq_printf(f,
996-
"rateNoSleepAlloc: %8d pages/sec\n"
997-
"rateSleepAlloc: %8d pages/sec\n"
998-
"rateFree: %8d pages/sec\n",
999-
VMW_BALLOON_NOSLEEP_ALLOC_MAX,
1000-
b->rate_alloc, b->rate_free);
964+
"rateSleepAlloc: %8d pages/sec\n",
965+
b->rate_alloc);
1001966

1002967
seq_printf(f,
1003968
"\n"
@@ -1088,7 +1053,6 @@ static int __init vmballoon_init(void)
10881053

10891054
/* initialize rates */
10901055
balloon.rate_alloc = VMW_BALLOON_RATE_ALLOC_MAX;
1091-
balloon.rate_free = VMW_BALLOON_RATE_FREE_MAX;
10921056

10931057
INIT_DELAYED_WORK(&balloon.dwork, vmballoon_work);
10941058

0 commit comments

Comments
 (0)