ia64/linux-2.6.18-xen.hg

view drivers/md/dm-round-robin.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 * Copyright (C) 2003 Sistina Software.
3 * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
4 *
5 * Module Author: Heinz Mauelshagen
6 *
7 * This file is released under the GPL.
8 *
9 * Round-robin path selector.
10 */
12 #include "dm.h"
13 #include "dm-path-selector.h"
15 #include <linux/slab.h>
17 #define DM_MSG_PREFIX "multipath round-robin"
19 /*-----------------------------------------------------------------
20 * Path-handling code, paths are held in lists
21 *---------------------------------------------------------------*/
22 struct path_info {
23 struct list_head list;
24 struct path *path;
25 unsigned repeat_count;
26 };
28 static void free_paths(struct list_head *paths)
29 {
30 struct path_info *pi, *next;
32 list_for_each_entry_safe(pi, next, paths, list) {
33 list_del(&pi->list);
34 kfree(pi);
35 }
36 }
38 /*-----------------------------------------------------------------
39 * Round-robin selector
40 *---------------------------------------------------------------*/
42 #define RR_MIN_IO 1000
44 struct selector {
45 struct list_head valid_paths;
46 struct list_head invalid_paths;
47 };
49 static struct selector *alloc_selector(void)
50 {
51 struct selector *s = kmalloc(sizeof(*s), GFP_KERNEL);
53 if (s) {
54 INIT_LIST_HEAD(&s->valid_paths);
55 INIT_LIST_HEAD(&s->invalid_paths);
56 }
58 return s;
59 }
61 static int rr_create(struct path_selector *ps, unsigned argc, char **argv)
62 {
63 struct selector *s;
65 s = alloc_selector();
66 if (!s)
67 return -ENOMEM;
69 ps->context = s;
70 return 0;
71 }
73 static void rr_destroy(struct path_selector *ps)
74 {
75 struct selector *s = (struct selector *) ps->context;
77 free_paths(&s->valid_paths);
78 free_paths(&s->invalid_paths);
79 kfree(s);
80 ps->context = NULL;
81 }
83 static int rr_status(struct path_selector *ps, struct path *path,
84 status_type_t type, char *result, unsigned int maxlen)
85 {
86 struct path_info *pi;
87 int sz = 0;
89 if (!path)
90 DMEMIT("0 ");
91 else {
92 switch(type) {
93 case STATUSTYPE_INFO:
94 break;
95 case STATUSTYPE_TABLE:
96 pi = path->pscontext;
97 DMEMIT("%u ", pi->repeat_count);
98 break;
99 }
100 }
102 return sz;
103 }
105 /*
106 * Called during initialisation to register each path with an
107 * optional repeat_count.
108 */
109 static int rr_add_path(struct path_selector *ps, struct path *path,
110 int argc, char **argv, char **error)
111 {
112 struct selector *s = (struct selector *) ps->context;
113 struct path_info *pi;
114 unsigned repeat_count = RR_MIN_IO;
116 if (argc > 1) {
117 *error = "round-robin ps: incorrect number of arguments";
118 return -EINVAL;
119 }
121 /* First path argument is number of I/Os before switching path */
122 if ((argc == 1) && (sscanf(argv[0], "%u", &repeat_count) != 1)) {
123 *error = "round-robin ps: invalid repeat count";
124 return -EINVAL;
125 }
127 /* allocate the path */
128 pi = kmalloc(sizeof(*pi), GFP_KERNEL);
129 if (!pi) {
130 *error = "round-robin ps: Error allocating path context";
131 return -ENOMEM;
132 }
134 pi->path = path;
135 pi->repeat_count = repeat_count;
137 path->pscontext = pi;
139 list_add(&pi->list, &s->valid_paths);
141 return 0;
142 }
144 static void rr_fail_path(struct path_selector *ps, struct path *p)
145 {
146 struct selector *s = (struct selector *) ps->context;
147 struct path_info *pi = p->pscontext;
149 list_move(&pi->list, &s->invalid_paths);
150 }
152 static int rr_reinstate_path(struct path_selector *ps, struct path *p)
153 {
154 struct selector *s = (struct selector *) ps->context;
155 struct path_info *pi = p->pscontext;
157 list_move(&pi->list, &s->valid_paths);
159 return 0;
160 }
162 static struct path *rr_select_path(struct path_selector *ps,
163 unsigned *repeat_count)
164 {
165 struct selector *s = (struct selector *) ps->context;
166 struct path_info *pi = NULL;
168 if (!list_empty(&s->valid_paths)) {
169 pi = list_entry(s->valid_paths.next, struct path_info, list);
170 list_move_tail(&pi->list, &s->valid_paths);
171 *repeat_count = pi->repeat_count;
172 }
174 return pi ? pi->path : NULL;
175 }
177 static struct path_selector_type rr_ps = {
178 .name = "round-robin",
179 .module = THIS_MODULE,
180 .table_args = 1,
181 .info_args = 0,
182 .create = rr_create,
183 .destroy = rr_destroy,
184 .status = rr_status,
185 .add_path = rr_add_path,
186 .fail_path = rr_fail_path,
187 .reinstate_path = rr_reinstate_path,
188 .select_path = rr_select_path,
189 };
191 static int __init dm_rr_init(void)
192 {
193 int r = dm_register_path_selector(&rr_ps);
195 if (r < 0)
196 DMERR("register failed %d", r);
198 DMINFO("version 1.0.0 loaded");
200 return r;
201 }
203 static void __exit dm_rr_exit(void)
204 {
205 int r = dm_unregister_path_selector(&rr_ps);
207 if (r < 0)
208 DMERR("round-robin: unregister failed %d", r);
209 }
211 module_init(dm_rr_init);
212 module_exit(dm_rr_exit);
214 MODULE_DESCRIPTION(DM_NAME " round-robin multipath path selector");
215 MODULE_AUTHOR("Sistina Software <dm-devel@redhat.com>");
216 MODULE_LICENSE("GPL");