ia64/linux-2.6.18-xen.hg

view drivers/md/dm-hw-handler.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) 2004 Red Hat, Inc. All rights reserved.
3 *
4 * This file is released under the GPL.
5 *
6 * Multipath hardware handler registration.
7 */
9 #include "dm.h"
10 #include "dm-hw-handler.h"
12 #include <linux/slab.h>
14 struct hwh_internal {
15 struct hw_handler_type hwht;
17 struct list_head list;
18 long use;
19 };
21 #define hwht_to_hwhi(__hwht) container_of((__hwht), struct hwh_internal, hwht)
23 static LIST_HEAD(_hw_handlers);
24 static DECLARE_RWSEM(_hwh_lock);
26 static struct hwh_internal *__find_hw_handler_type(const char *name)
27 {
28 struct hwh_internal *hwhi;
30 list_for_each_entry(hwhi, &_hw_handlers, list) {
31 if (!strcmp(name, hwhi->hwht.name))
32 return hwhi;
33 }
35 return NULL;
36 }
38 static struct hwh_internal *get_hw_handler(const char *name)
39 {
40 struct hwh_internal *hwhi;
42 down_read(&_hwh_lock);
43 hwhi = __find_hw_handler_type(name);
44 if (hwhi) {
45 if ((hwhi->use == 0) && !try_module_get(hwhi->hwht.module))
46 hwhi = NULL;
47 else
48 hwhi->use++;
49 }
50 up_read(&_hwh_lock);
52 return hwhi;
53 }
55 struct hw_handler_type *dm_get_hw_handler(const char *name)
56 {
57 struct hwh_internal *hwhi;
59 if (!name)
60 return NULL;
62 hwhi = get_hw_handler(name);
63 if (!hwhi) {
64 request_module("dm-%s", name);
65 hwhi = get_hw_handler(name);
66 }
68 return hwhi ? &hwhi->hwht : NULL;
69 }
71 void dm_put_hw_handler(struct hw_handler_type *hwht)
72 {
73 struct hwh_internal *hwhi;
75 if (!hwht)
76 return;
78 down_read(&_hwh_lock);
79 hwhi = __find_hw_handler_type(hwht->name);
80 if (!hwhi)
81 goto out;
83 if (--hwhi->use == 0)
84 module_put(hwhi->hwht.module);
86 BUG_ON(hwhi->use < 0);
88 out:
89 up_read(&_hwh_lock);
90 }
92 static struct hwh_internal *_alloc_hw_handler(struct hw_handler_type *hwht)
93 {
94 struct hwh_internal *hwhi = kmalloc(sizeof(*hwhi), GFP_KERNEL);
96 if (hwhi) {
97 memset(hwhi, 0, sizeof(*hwhi));
98 hwhi->hwht = *hwht;
99 }
101 return hwhi;
102 }
104 int dm_register_hw_handler(struct hw_handler_type *hwht)
105 {
106 int r = 0;
107 struct hwh_internal *hwhi = _alloc_hw_handler(hwht);
109 if (!hwhi)
110 return -ENOMEM;
112 down_write(&_hwh_lock);
114 if (__find_hw_handler_type(hwht->name)) {
115 kfree(hwhi);
116 r = -EEXIST;
117 } else
118 list_add(&hwhi->list, &_hw_handlers);
120 up_write(&_hwh_lock);
122 return r;
123 }
125 int dm_unregister_hw_handler(struct hw_handler_type *hwht)
126 {
127 struct hwh_internal *hwhi;
129 down_write(&_hwh_lock);
131 hwhi = __find_hw_handler_type(hwht->name);
132 if (!hwhi) {
133 up_write(&_hwh_lock);
134 return -EINVAL;
135 }
137 if (hwhi->use) {
138 up_write(&_hwh_lock);
139 return -ETXTBSY;
140 }
142 list_del(&hwhi->list);
144 up_write(&_hwh_lock);
146 kfree(hwhi);
148 return 0;
149 }
151 unsigned dm_scsi_err_handler(struct hw_handler *hwh, struct bio *bio)
152 {
153 #if 0
154 int sense_key, asc, ascq;
156 if (bio->bi_error & BIO_SENSE) {
157 /* FIXME: This is just an initial guess. */
158 /* key / asc / ascq */
159 sense_key = (bio->bi_error >> 16) & 0xff;
160 asc = (bio->bi_error >> 8) & 0xff;
161 ascq = bio->bi_error & 0xff;
163 switch (sense_key) {
164 /* This block as a whole comes from the device.
165 * So no point retrying on another path. */
166 case 0x03: /* Medium error */
167 case 0x05: /* Illegal request */
168 case 0x07: /* Data protect */
169 case 0x08: /* Blank check */
170 case 0x0a: /* copy aborted */
171 case 0x0c: /* obsolete - no clue ;-) */
172 case 0x0d: /* volume overflow */
173 case 0x0e: /* data miscompare */
174 case 0x0f: /* reserved - no idea either. */
175 return MP_ERROR_IO;
177 /* For these errors it's unclear whether they
178 * come from the device or the controller.
179 * So just lets try a different path, and if
180 * it eventually succeeds, user-space will clear
181 * the paths again... */
182 case 0x02: /* Not ready */
183 case 0x04: /* Hardware error */
184 case 0x09: /* vendor specific */
185 case 0x0b: /* Aborted command */
186 return MP_FAIL_PATH;
188 case 0x06: /* Unit attention - might want to decode */
189 if (asc == 0x04 && ascq == 0x01)
190 /* "Unit in the process of
191 * becoming ready" */
192 return 0;
193 return MP_FAIL_PATH;
195 /* FIXME: For Unit Not Ready we may want
196 * to have a generic pg activation
197 * feature (START_UNIT). */
199 /* Should these two ever end up in the
200 * error path? I don't think so. */
201 case 0x00: /* No sense */
202 case 0x01: /* Recovered error */
203 return 0;
204 }
205 }
206 #endif
208 /* We got no idea how to decode the other kinds of errors ->
209 * assume generic error condition. */
210 return MP_FAIL_PATH;
211 }
213 EXPORT_SYMBOL_GPL(dm_register_hw_handler);
214 EXPORT_SYMBOL_GPL(dm_unregister_hw_handler);
215 EXPORT_SYMBOL_GPL(dm_scsi_err_handler);