ia64/linux-2.6.18-xen.hg

view lib/plist.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
line source
1 /*
2 * lib/plist.c
3 *
4 * Descending-priority-sorted double-linked list
5 *
6 * (C) 2002-2003 Intel Corp
7 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>.
8 *
9 * 2001-2005 (c) MontaVista Software, Inc.
10 * Daniel Walker <dwalker@mvista.com>
11 *
12 * (C) 2005 Thomas Gleixner <tglx@linutronix.de>
13 *
14 * Simplifications of the original code by
15 * Oleg Nesterov <oleg@tv-sign.ru>
16 *
17 * Licensed under the FSF's GNU Public License v2 or later.
18 *
19 * Based on simple lists (include/linux/list.h).
20 *
21 * This file contains the add / del functions which are considered to
22 * be too large to inline. See include/linux/plist.h for further
23 * information.
24 */
26 #include <linux/plist.h>
27 #include <linux/spinlock.h>
29 #ifdef CONFIG_DEBUG_PI_LIST
31 static void plist_check_prev_next(struct list_head *t, struct list_head *p,
32 struct list_head *n)
33 {
34 if (n->prev != p || p->next != n) {
35 printk("top: %p, n: %p, p: %p\n", t, t->next, t->prev);
36 printk("prev: %p, n: %p, p: %p\n", p, p->next, p->prev);
37 printk("next: %p, n: %p, p: %p\n", n, n->next, n->prev);
38 WARN_ON(1);
39 }
40 }
42 static void plist_check_list(struct list_head *top)
43 {
44 struct list_head *prev = top, *next = top->next;
46 plist_check_prev_next(top, prev, next);
47 while (next != top) {
48 prev = next;
49 next = prev->next;
50 plist_check_prev_next(top, prev, next);
51 }
52 }
54 static void plist_check_head(struct plist_head *head)
55 {
56 WARN_ON(!head->lock);
57 if (head->lock)
58 WARN_ON_SMP(!spin_is_locked(head->lock));
59 plist_check_list(&head->prio_list);
60 plist_check_list(&head->node_list);
61 }
63 #else
64 # define plist_check_head(h) do { } while (0)
65 #endif
67 /**
68 * plist_add - add @node to @head
69 *
70 * @node: &struct plist_node pointer
71 * @head: &struct plist_head pointer
72 */
73 void plist_add(struct plist_node *node, struct plist_head *head)
74 {
75 struct plist_node *iter;
77 plist_check_head(head);
78 WARN_ON(!plist_node_empty(node));
80 list_for_each_entry(iter, &head->prio_list, plist.prio_list) {
81 if (node->prio < iter->prio)
82 goto lt_prio;
83 else if (node->prio == iter->prio) {
84 iter = list_entry(iter->plist.prio_list.next,
85 struct plist_node, plist.prio_list);
86 goto eq_prio;
87 }
88 }
90 lt_prio:
91 list_add_tail(&node->plist.prio_list, &iter->plist.prio_list);
92 eq_prio:
93 list_add_tail(&node->plist.node_list, &iter->plist.node_list);
95 plist_check_head(head);
96 }
98 /**
99 * plist_del - Remove a @node from plist.
100 *
101 * @node: &struct plist_node pointer - entry to be removed
102 * @head: &struct plist_head pointer - list head
103 */
104 void plist_del(struct plist_node *node, struct plist_head *head)
105 {
106 plist_check_head(head);
108 if (!list_empty(&node->plist.prio_list)) {
109 struct plist_node *next = plist_first(&node->plist);
111 list_move_tail(&next->plist.prio_list, &node->plist.prio_list);
112 list_del_init(&node->plist.prio_list);
113 }
115 list_del_init(&node->plist.node_list);
117 plist_check_head(head);
118 }