lkml.org 
[lkml]   [2015]   [Apr]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4/9] VMware balloon: Update balloon target on each lock/unlock.
    Date
    From: Xavier Deguillard <xdeguillard@vmware.com>

    Instead of waiting for the next GET_TARGET command, we can react faster
    by exploiting the fact that each hypervisor call also returns the
    balloon target.

    Signed-off-by: Xavier Deguillard <xdeguillard@vmware.com>
    Acked-by: Dmitry Torokhov <dtor@vmware.com>
    Signed-off-by: Philip P. Moltmann <moltmann@vmware.com>
    Acked-by: Andy King <acking@vmware.com>
    ---
    drivers/misc/vmw_balloon.c | 85 +++++++++++++++++++++++-----------------------
    1 file changed, 42 insertions(+), 43 deletions(-)

    diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c
    index f65c676..72247d9 100644
    --- a/drivers/misc/vmw_balloon.c
    +++ b/drivers/misc/vmw_balloon.c
    @@ -46,7 +46,7 @@

    MODULE_AUTHOR("VMware, Inc.");
    MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver");
    -MODULE_VERSION("1.3.1.0-k");
    +MODULE_VERSION("1.3.2.0-k");
    MODULE_ALIAS("dmi:*:svnVMware*:*");
    MODULE_ALIAS("vmware_vmmemctl");
    MODULE_LICENSE("GPL");
    @@ -254,8 +254,10 @@ struct vmballoon;

    struct vmballoon_ops {
    void (*add_page)(struct vmballoon *b, int idx, struct page *p);
    - int (*lock)(struct vmballoon *b, unsigned int num_pages);
    - int (*unlock)(struct vmballoon *b, unsigned int num_pages);
    + int (*lock)(struct vmballoon *b, unsigned int num_pages,
    + unsigned int *target);
    + int (*unlock)(struct vmballoon *b, unsigned int num_pages,
    + unsigned int *target);
    };

    struct vmballoon {
    @@ -412,7 +414,7 @@ static bool vmballoon_send_get_target(struct vmballoon *b, u32 *new_target)
    * check the return value and maybe submit a different page.
    */
    static int vmballoon_send_lock_page(struct vmballoon *b, unsigned long pfn,
    - unsigned int *hv_status)
    + unsigned int *hv_status, unsigned int *target)
    {
    unsigned long status, dummy = 0;
    u32 pfn32;
    @@ -423,7 +425,7 @@ static int vmballoon_send_lock_page(struct vmballoon *b, unsigned long pfn,

    STATS_INC(b->stats.lock);

    - *hv_status = status = VMWARE_BALLOON_CMD(LOCK, pfn, dummy, dummy);
    + *hv_status = status = VMWARE_BALLOON_CMD(LOCK, pfn, dummy, *target);
    if (vmballoon_check_status(b, status))
    return 0;

    @@ -433,14 +435,14 @@ static int vmballoon_send_lock_page(struct vmballoon *b, unsigned long pfn,
    }

    static int vmballoon_send_batched_lock(struct vmballoon *b,
    - unsigned int num_pages)
    + unsigned int num_pages, unsigned int *target)
    {
    - unsigned long status, dummy;
    + unsigned long status;
    unsigned long pfn = page_to_pfn(b->page);

    STATS_INC(b->stats.lock);

    - status = VMWARE_BALLOON_CMD(BATCHED_LOCK, pfn, num_pages, dummy);
    + status = VMWARE_BALLOON_CMD(BATCHED_LOCK, pfn, num_pages, *target);
    if (vmballoon_check_status(b, status))
    return 0;

    @@ -453,7 +455,8 @@ static int vmballoon_send_batched_lock(struct vmballoon *b,
    * Notify the host that guest intends to release given page back into
    * the pool of available (to the guest) pages.
    */
    -static bool vmballoon_send_unlock_page(struct vmballoon *b, unsigned long pfn)
    +static bool vmballoon_send_unlock_page(struct vmballoon *b, unsigned long pfn,
    + unsigned int *target)
    {
    unsigned long status, dummy = 0;
    u32 pfn32;
    @@ -464,7 +467,7 @@ static bool vmballoon_send_unlock_page(struct vmballoon *b, unsigned long pfn)

    STATS_INC(b->stats.unlock);

    - status = VMWARE_BALLOON_CMD(UNLOCK, pfn, dummy, dummy);
    + status = VMWARE_BALLOON_CMD(UNLOCK, pfn, dummy, *target);
    if (vmballoon_check_status(b, status))
    return true;

    @@ -474,14 +477,14 @@ static bool vmballoon_send_unlock_page(struct vmballoon *b, unsigned long pfn)
    }

    static bool vmballoon_send_batched_unlock(struct vmballoon *b,
    - unsigned int num_pages)
    + unsigned int num_pages, unsigned int *target)
    {
    - unsigned long status, dummy;
    + unsigned long status;
    unsigned long pfn = page_to_pfn(b->page);

    STATS_INC(b->stats.unlock);

    - status = VMWARE_BALLOON_CMD(BATCHED_UNLOCK, pfn, num_pages, dummy);
    + status = VMWARE_BALLOON_CMD(BATCHED_UNLOCK, pfn, num_pages, *target);
    if (vmballoon_check_status(b, status))
    return true;

    @@ -527,12 +530,14 @@ static void vmballoon_pop(struct vmballoon *b)
    * refuse list, those refused page are then released at the end of the
    * inflation cycle.
    */
    -static int vmballoon_lock_page(struct vmballoon *b, unsigned int num_pages)
    +static int vmballoon_lock_page(struct vmballoon *b, unsigned int num_pages,
    + unsigned int *target)
    {
    int locked, hv_status;
    struct page *page = b->page;

    - locked = vmballoon_send_lock_page(b, page_to_pfn(page), &hv_status);
    + locked = vmballoon_send_lock_page(b, page_to_pfn(page), &hv_status,
    + target);
    if (locked > 0) {
    STATS_INC(b->stats.refused_alloc);

    @@ -566,11 +571,11 @@ static int vmballoon_lock_page(struct vmballoon *b, unsigned int num_pages)
    }

    static int vmballoon_lock_batched_page(struct vmballoon *b,
    - unsigned int num_pages)
    + unsigned int num_pages, unsigned int *target)
    {
    int locked, i;

    - locked = vmballoon_send_batched_lock(b, num_pages);
    + locked = vmballoon_send_batched_lock(b, num_pages, target);
    if (locked > 0) {
    for (i = 0; i < num_pages; i++) {
    u64 pa = vmballoon_batch_get_pa(b->batch_page, i);
    @@ -619,11 +624,12 @@ static int vmballoon_lock_batched_page(struct vmballoon *b,
    * the host so it can make sure the page will be available for the guest
    * to use, if needed.
    */
    -static int vmballoon_unlock_page(struct vmballoon *b, unsigned int num_pages)
    +static int vmballoon_unlock_page(struct vmballoon *b, unsigned int num_pages,
    + unsigned int *target)
    {
    struct page *page = b->page;

    - if (!vmballoon_send_unlock_page(b, page_to_pfn(page))) {
    + if (!vmballoon_send_unlock_page(b, page_to_pfn(page), target)) {
    list_add(&page->lru, &b->pages);
    return -EIO;
    }
    @@ -639,12 +645,12 @@ static int vmballoon_unlock_page(struct vmballoon *b, unsigned int num_pages)
    }

    static int vmballoon_unlock_batched_page(struct vmballoon *b,
    - unsigned int num_pages)
    + unsigned int num_pages, unsigned int *target)
    {
    int locked, i, ret = 0;
    bool hv_success;

    - hv_success = vmballoon_send_batched_unlock(b, num_pages);
    + hv_success = vmballoon_send_batched_unlock(b, num_pages, target);
    if (!hv_success)
    ret = -EIO;

    @@ -709,9 +715,7 @@ static void vmballoon_add_batched_page(struct vmballoon *b, int idx,
    */
    static void vmballoon_inflate(struct vmballoon *b)
    {
    - unsigned int goal;
    unsigned int rate;
    - unsigned int i;
    unsigned int allocations = 0;
    unsigned int num_pages = 0;
    int error = 0;
    @@ -734,7 +738,6 @@ static void vmballoon_inflate(struct vmballoon *b)
    * slowdown page allocations considerably.
    */

    - goal = b->target - b->size;
    /*
    * Start with no sleep allocation rate which may be higher
    * than sleeping allocation rate.
    @@ -743,16 +746,17 @@ static void vmballoon_inflate(struct vmballoon *b)
    b->rate_alloc : VMW_BALLOON_NOSLEEP_ALLOC_MAX;

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

    - for (i = 0; i < goal; i++) {
    - struct page *page = alloc_page(flags);
    + while (b->size < b->target && num_pages < b->target - b->size) {
    + struct page *page;

    if (flags == VMW_PAGE_ALLOC_NOSLEEP)
    STATS_INC(b->stats.alloc);
    else
    STATS_INC(b->stats.sleep_alloc);

    + page = alloc_page(flags);
    if (!page) {
    if (flags == VMW_PAGE_ALLOC_CANSLEEP) {
    /*
    @@ -777,7 +781,7 @@ static void vmballoon_inflate(struct vmballoon *b)
    */
    b->slow_allocation_cycles = VMW_BALLOON_SLOW_CYCLES;

    - if (i >= b->rate_alloc)
    + if (allocations >= b->rate_alloc)
    break;

    flags = VMW_PAGE_ALLOC_CANSLEEP;
    @@ -788,7 +792,7 @@ static void vmballoon_inflate(struct vmballoon *b)

    b->ops->add_page(b, num_pages++, page);
    if (num_pages == b->batch_max_pages) {
    - error = b->ops->lock(b, num_pages);
    + error = b->ops->lock(b, num_pages, &b->target);
    num_pages = 0;
    if (error)
    break;
    @@ -799,21 +803,21 @@ static void vmballoon_inflate(struct vmballoon *b)
    allocations = 0;
    }

    - if (i >= rate) {
    + if (allocations >= rate) {
    /* We allocated enough pages, let's take a break. */
    break;
    }
    }

    if (num_pages > 0)
    - b->ops->lock(b, num_pages);
    + b->ops->lock(b, num_pages, &b->target);

    /*
    * We reached our goal without failures so try increasing
    * allocation rate.
    */
    - if (error == 0 && i >= b->rate_alloc) {
    - unsigned int mult = i / b->rate_alloc;
    + if (error == 0 && allocations >= b->rate_alloc) {
    + unsigned int mult = allocations / b->rate_alloc;

    b->rate_alloc =
    min(b->rate_alloc + mult * VMW_BALLOON_RATE_ALLOC_INC,
    @@ -830,16 +834,11 @@ static void vmballoon_deflate(struct vmballoon *b)
    {
    struct page *page, *next;
    unsigned int i = 0;
    - unsigned int goal;
    unsigned int num_pages = 0;
    int error;

    - pr_debug("%s - size: %d, target %d\n", __func__, b->size, b->target);
    -
    - /* limit deallocation rate */
    - goal = min(b->size - b->target, b->rate_free);
    -
    - pr_debug("%s - goal: %d, rate: %d\n", __func__, goal, b->rate_free);
    + pr_debug("%s - size: %d, target %d, rate: %d\n", __func__, b->size,
    + b->target, b->rate_free);

    /* free pages to reach target */
    list_for_each_entry_safe(page, next, &b->pages, lru) {
    @@ -847,7 +846,7 @@ static void vmballoon_deflate(struct vmballoon *b)
    b->ops->add_page(b, num_pages++, page);

    if (num_pages == b->batch_max_pages) {
    - error = b->ops->unlock(b, num_pages);
    + error = b->ops->unlock(b, num_pages, &b->target);
    num_pages = 0;
    if (error) {
    /* quickly decrease rate in case of error */
    @@ -857,12 +856,12 @@ static void vmballoon_deflate(struct vmballoon *b)
    }
    }

    - if (++i >= goal)
    + if (++i >= b->size - b->target)
    break;
    }

    if (num_pages > 0)
    - b->ops->unlock(b, num_pages);
    + b->ops->unlock(b, num_pages, &b->target);

    /* slowly increase rate if there were no errors */
    if (error == 0)
    --
    1.9.3


    \
     
     \ /
      Last update: 2015-04-14 19:41    [W:2.671 / U:0.308 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site