]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Update the guest balloon target after each LOCK and UNLOCK.
authorVMware, Inc <>
Wed, 26 Dec 2012 21:16:03 +0000 (13:16 -0800)
committerDmitry Torokhov <dtor@vmware.com>
Thu, 27 Dec 2012 18:51:43 +0000 (10:51 -0800)
Currently, the guest driver won't update the target, until the
next GET_TARGET command, thus at maximum, the guest can try to
reclaim 16k pages before updating the balloon target. Those 16k
pages will be considered unneeded by the monitor, and so will
be rejected.

For every command, the monitor put the balloon target in %ebx.
Use that value to dynamically update the balloon target after
each LOCK and UNLOCK commands, that way, the guest driver can
react much faster to change than before.

As a consequence, there will be less "unneeded bpn" message in
the vmware.log file. Only one per second in the unbatched path,
and a maximum of 512 in the batched one.

Signed-off-by: Dmitry Torokhov <dtor@vmware.com>
open-vm-tools/modules/shared/vmmemctl/backdoor_balloon.c
open-vm-tools/modules/shared/vmmemctl/backdoor_balloon.h
open-vm-tools/modules/shared/vmmemctl/vmballoon.c
open-vm-tools/modules/shared/vmmemctl/vmballoon.h

index 495012847699807e33120912b3d3ce55dd797cda..ccdf98e0bb83d54c4ac14c462b98d3d543f3fd57 100644 (file)
@@ -271,8 +271,9 @@ Backdoor_MonitorGetTarget(Balloon *b,     // IN
  */
 
 int
-Backdoor_MonitorLockPage(Balloon *b,    // IN
-                         PPN64 ppn)     // IN
+Backdoor_MonitorLockPage(Balloon *b,     // IN
+                         PPN64 ppn,      // IN
+                         uint32 *target) // OUT
 {
    int status;
    uint32 ppn32 = (uint32)ppn;
@@ -282,7 +283,7 @@ Backdoor_MonitorLockPage(Balloon *b,    // IN
       return BALLOON_ERROR_PPN_INVALID;
    }
 
-   status = BackdoorCmd(BALLOON_BDOOR_CMD_LOCK, ppn32, 0, NULL,
+   status = BackdoorCmd(BALLOON_BDOOR_CMD_LOCK, ppn32, 0, target,
                         &b->resetFlag);
 
    /* update stats */
@@ -314,8 +315,9 @@ Backdoor_MonitorLockPage(Balloon *b,    // IN
  */
 
 int
-Backdoor_MonitorUnlockPage(Balloon *b,  // IN
-                           PPN64 ppn)   // IN
+Backdoor_MonitorUnlockPage(Balloon *b,     // IN
+                           PPN64 ppn,      // IN
+                           uint32 *target) // OUT
 {
    int status;
    uint32 ppn32 = (uint32)ppn;
@@ -325,7 +327,7 @@ Backdoor_MonitorUnlockPage(Balloon *b,  // IN
       return BALLOON_ERROR_PPN_INVALID;
    }
 
-   status = BackdoorCmd(BALLOON_BDOOR_CMD_UNLOCK, ppn32, 0, NULL,
+   status = BackdoorCmd(BALLOON_BDOOR_CMD_UNLOCK, ppn32, 0, target,
                         &b->resetFlag);
 
    /* update stats */
@@ -354,12 +356,13 @@ Backdoor_MonitorUnlockPage(Balloon *b,  // IN
  */
 
 int
-Backdoor_MonitorLockPagesBatched(Balloon *b,    // IN
-                                 PPN64 ppn,     // IN
-                                 uint32 nPages) // IN
+Backdoor_MonitorLockPagesBatched(Balloon *b,     // IN
+                                 PPN64 ppn,      // IN
+                                 uint32 nPages,  // IN
+                                 uint32 *target) // OUT
 {
    int status = BackdoorCmd(BALLOON_BDOOR_CMD_BATCHED_LOCK,
-                            (size_t)ppn, nPages, NULL, &b->resetFlag);
+                            (size_t)ppn, nPages, target, &b->resetFlag);
 
    /* update stats */
    STATS_INC(b->stats.lock);
@@ -389,10 +392,11 @@ Backdoor_MonitorLockPagesBatched(Balloon *b,    // IN
 int
 Backdoor_MonitorUnlockPagesBatched(Balloon *b,          // IN
                                    PPN64 ppn,           // IN
-                                   uint32 nPages)       // IN
+                                   uint32 nPages,       // IN
+                                   uint32 *target)      // OUT
 {
    int status = BackdoorCmd(BALLOON_BDOOR_CMD_BATCHED_UNLOCK,
-                            (size_t)ppn, nPages, NULL, &b->resetFlag);
+                            (size_t)ppn, nPages, target, &b->resetFlag);
 
    /* update stats */
    STATS_INC(b->stats.unlock);
index 3cb53296a77be59eebc1046563a89e434e4b6b8f..f228980212d2c43f7aa7028e3c5bb92c9037d75a 100644 (file)
 int Backdoor_MonitorStart(Balloon *b, uint32 protoVersion);
 int Backdoor_MonitorGuestType(Balloon *b);
 int Backdoor_MonitorGetTarget(Balloon *b, uint32 *target);
-int Backdoor_MonitorLockPage(Balloon *b, PPN64 ppn);
-int Backdoor_MonitorUnlockPage(Balloon *b, PPN64 ppn);
-int Backdoor_MonitorLockPagesBatched(Balloon *b, PPN64 ppn, uint32 nPages);
-int Backdoor_MonitorUnlockPagesBatched(Balloon *b, PPN64 ppn, uint32 nPages);
+int Backdoor_MonitorLockPage(Balloon *b, PPN64 ppn, uint32 *target);
+int Backdoor_MonitorUnlockPage(Balloon *b, PPN64 ppn, uint32 *target);
+int Backdoor_MonitorLockPagesBatched(Balloon *b, PPN64 ppn, uint32 nPages,
+                                     uint32 *target);
+int Backdoor_MonitorUnlockPagesBatched(Balloon *b, PPN64 ppn, uint32 nPages,
+                                       uint32 *target);
 
 #endif /* _BACKDOOR_BALLOON_H_ */
index cb62a8c2c442ff320488f8a780e77cc9dfdd81b5..59a05dca071a022be2519444893fbe060ed4db6c 100644 (file)
@@ -111,10 +111,10 @@ static void BalloonReset(Balloon *b);
 
 static void BalloonAddPage(Balloon *b, uint16 idx, PageHandle page);
 static void BalloonAddPageBatched(Balloon *b, uint16 idx, PageHandle page);
-static int  BalloonLock(Balloon *b, uint16 nPages);
-static int  BalloonLockBatched(Balloon *b, uint16 nPages);
-static int  BalloonUnlock(Balloon *b, uint16 nPages);
-static int  BalloonUnlockBatched(Balloon *b, uint16 nPages);
+static int  BalloonLock(Balloon *b, uint16 nPages, uint32 *target);
+static int  BalloonLockBatched(Balloon *b, uint16 nPages, uint32 *target);
+static int  BalloonUnlock(Balloon *b, uint16 nPages, uint32 *target);
+static int  BalloonUnlockBatched(Balloon *b, uint16 nPages, uint32 *target);
 
 /*
  * Globals
@@ -651,7 +651,7 @@ BalloonPageFree(Balloon *b)     // IN
  *      Attempts to allocate physical pages to inflate balloon.
  *
  * Results:
- *      Returns BALLOON_SUCCESS if successful, otherwise error code.
+ *      Returns BALLOON_SUCCESS.
  *
  * Side effects:
  *      None.
@@ -663,9 +663,8 @@ static int
 BalloonInflate(Balloon *b,      // IN
                uint32 target)   // IN
 {
-   uint32 goal, nPages;
+   uint32 nPages;
    unsigned int rate;
-   unsigned int i;
    unsigned int allocations = 0;
    int status = 0;
    BalloonPageAllocType allocType = BALLOON_PAGE_ALLOC_NOSLEEP;
@@ -685,7 +684,6 @@ BalloonInflate(Balloon *b,      // IN
     * slowdown page allocations considerably.
     */
 
-   goal = target - b->nPages;
    /*
     * Start with no sleep allocation rate which may be higher
     * than sleeping allocation rate.
@@ -694,14 +692,15 @@ BalloonInflate(Balloon *b,      // IN
                 b->rateAlloc : BALLOON_NOSLEEP_ALLOC_MAX;
 
    nPages = 0;
-   for (i = 0; i < goal; i++) {
-      PageHandle        handle;
+   while (b->nPages < target && nPages < target - b->nPages) {
+      PageHandle handle;
 
       STATS_INC(b->stats.primAlloc[allocType]);
       handle = OS_ReservedPageAlloc(allocType);
       if (handle == PAGE_HANDLE_INVALID) {
          STATS_INC(b->stats.primAllocFail[allocType]);
 
+         status = BALLOON_PAGE_ALLOC_FAILURE;
          if (allocType == BALLOON_PAGE_ALLOC_CANSLEEP) {
             /*
              * CANSLEEP page allocation failed, so guest is under severe
@@ -729,11 +728,11 @@ BalloonInflate(Balloon *b,      // IN
          rate = b->rateAlloc;
          continue;
       }
-
       allocations++;
+
       b->balloonOps->addPage(b, nPages++, handle);
       if (nPages == b->batchMaxPages) {
-         status = b->balloonOps->lock(b, nPages);
+         status = b->balloonOps->lock(b, nPages, &target);
          nPages = 0;
 
          if (status != BALLOON_SUCCESS) {
@@ -752,15 +751,15 @@ BalloonInflate(Balloon *b,      // IN
    }
 
    if (nPages > 0) {
-      status = b->balloonOps->lock(b, nPages);
+      b->balloonOps->lock(b, nPages, NULL);
    }
 
    /*
     * We reached our goal without failures so try increasing
     * allocation rate.
     */
-   if (status == BALLOON_SUCCESS && i >= b->rateAlloc) {
-      unsigned int mult = i / b->rateAlloc;
+   if (status == BALLOON_SUCCESS && allocations >= b->rateAlloc) {
+      unsigned int mult = allocations / b->rateAlloc;
 
       b->rateAlloc = MIN(b->rateAlloc + mult * BALLOON_RATE_ALLOC_INC,
                          BALLOON_RATE_ALLOC_MAX);
@@ -771,7 +770,6 @@ BalloonInflate(Balloon *b,      // IN
    return BALLOON_SUCCESS;
 }
 
-
 /*
  *----------------------------------------------------------------------
  *
@@ -790,7 +788,8 @@ BalloonInflate(Balloon *b,      // IN
  */
 static int
 BalloonLockBatched(Balloon *b,       // IN
-                   uint16 nPages)    // IN
+                   uint16 nPages,    // IN
+                   uint32 *target)   // OUT
 {
    int          status;
    uint32       i;
@@ -810,7 +809,8 @@ BalloonLockBatched(Balloon *b,       // IN
    if (b->fallbackChunk == NULL) {
       status = BALLOON_PAGE_ALLOC_FAILURE;
    } else {
-      status = Backdoor_MonitorLockPagesBatched(b, batchPagePPN, nPages);
+      status = Backdoor_MonitorLockPagesBatched(b, batchPagePPN, nPages,
+                                                target);
    }
 
    if (status != BALLOON_SUCCESS) {
@@ -896,7 +896,8 @@ out:
  */
 static int
 BalloonUnlockBatched(Balloon *b,     // IN
-                     uint16 nPages)  // IN
+                     uint16 nPages,  // IN
+                     uint32 *target) // OUT
 {
    uint32 i;
    int status = BALLOON_SUCCESS;
@@ -905,7 +906,7 @@ BalloonUnlockBatched(Balloon *b,     // IN
    BalloonChunk *chunk = NULL;
 
    batchPagePPN = PA_2_PPN(OS_ReservedPageGetPA(b->pageHandle));
-   status = Backdoor_MonitorUnlockPagesBatched(b, batchPagePPN, nPages);
+   status = Backdoor_MonitorUnlockPagesBatched(b, batchPagePPN, nPages, target);
 
    if (status != BALLOON_SUCCESS) {
       for (i = 0; i < nPages; i++) {
@@ -990,7 +991,8 @@ BalloonAddPageBatched(Balloon *b,            // IN
 
 static int
 BalloonLock(Balloon *b,       // IN
-            uint16 nPages)    // IN
+            uint16 nPages,    // IN
+            uint32 *target)   // OUT
 {
    PPN pagePPN;
    BalloonChunk *chunk;
@@ -1006,7 +1008,7 @@ BalloonLock(Balloon *b,       // IN
 
    /* inform monitor via backdoor */
    pagePPN = PA_2_PPN(OS_ReservedPageGetPA(b->pageHandle));
-   status = Backdoor_MonitorLockPage(b, pagePPN);
+   status = Backdoor_MonitorLockPage(b, pagePPN, target);
    if (status != BALLOON_SUCCESS) {
       int old_status = status;
 
@@ -1057,10 +1059,11 @@ out:
 
 static int
 BalloonUnlock(Balloon *b,     // IN
-              uint16 nPages)  // IN
+              uint16 nPages,  // IN
+              uint32 *target) // OUT
 {
    PPN pagePPN = PA_2_PPN(OS_ReservedPageGetPA(b->pageHandle));
-   int status = Backdoor_MonitorUnlockPage(b, pagePPN);
+   int status = Backdoor_MonitorUnlockPage(b, pagePPN, target);
 
    if (status != BALLOON_SUCCESS) {
       BalloonChunk *chunk = BalloonGetChunkOrFallback(b);
@@ -1130,16 +1133,11 @@ BalloonDeflate(Balloon *b,      // IN
                uint32 target)   // IN
 {
    int                  status = BALLOON_SUCCESS;
-   uint32               goal, nPages;
+   uint32               nPages, deallocations = 0;
    BalloonChunk         *chunk = NULL;
 
-   goal = b->nPages - target;
-
-   /* limit deallocation rate */
-   goal = MIN(goal, b->rateFree);
-
    nPages = 0;
-   for ( ; goal > 0; goal--) {
+   while (b->nPages > target && nPages < b->nPages - target) {
       PageHandle lockedHandle;
 
       if (chunk == NULL) {
@@ -1164,30 +1162,36 @@ BalloonDeflate(Balloon *b,      // IN
          chunk = NULL;
       }
 
+      deallocations++;
       b->balloonOps->addPage(b, nPages++, lockedHandle);
       if (nPages == b->batchMaxPages) {
-         status = b->balloonOps->unlock(b, nPages);
+         status = b->balloonOps->unlock(b, nPages, &target);
          nPages = 0;
 
          if (status != BALLOON_SUCCESS) {
-            if (BALLOON_RATE_ADAPT) {
-               /* quickly decrease rate if error */
-               b->rateFree = MAX(b->rateFree / 2, BALLOON_RATE_FREE_MIN);
-            }
-            goto out;
+            break;
          }
+      }
 
+      if (deallocations >= b->rateFree) {
+         /* We released enough pages, let's take a break. */
+         break;
       }
    }
 
    if (nPages) {
-      status = b->balloonOps->unlock(b, nPages);
+      b->balloonOps->unlock(b, nPages, NULL);
    }
 
-   if (status == BALLOON_SUCCESS && BALLOON_RATE_ADAPT) {
-      /* slowly increase rate if no errors */
-      b->rateFree = MIN(b->rateFree + BALLOON_RATE_FREE_INC,
-                        BALLOON_RATE_FREE_MAX);
+   if (BALLOON_RATE_ADAPT) {
+      if (status == BALLOON_SUCCESS) {
+         /* slowly increase rate if no errors */
+         b->rateFree = MIN(b->rateFree + BALLOON_RATE_FREE_INC,
+                           BALLOON_RATE_FREE_MAX);
+      } else {
+         /* quickly decrease rate if error */
+         b->rateFree = MAX(b->rateFree / 2, BALLOON_RATE_FREE_MIN);
+      }
    }
 
 out:
index c8d5f0edeb9adb844db3711843955711082bd8e3..295b1b7b45c897c21ef3657dc7a1416037bff66d 100644 (file)
@@ -177,8 +177,8 @@ typedef struct {
 
 typedef struct BalloonOps {
    void (*addPage)(Balloon *b, uint16 idx, PageHandle page);
-   int (*lock)(Balloon *b, uint16 nPages);
-   int (*unlock)(Balloon *b, uint16 nPages);
+   int (*lock)(Balloon *b, uint16 nPages, uint32 *target);
+   int (*unlock)(Balloon *b, uint16 nPages, uint32 *target);
 } BalloonOps;
 
 /*