ia64/linux-2.6.18-xen.hg

view drivers/md/dm-stripe.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) 2001-2003 Sistina Software (UK) Limited.
3 *
4 * This file is released under the GPL.
5 */
7 #include "dm.h"
9 #include <linux/module.h>
10 #include <linux/init.h>
11 #include <linux/blkdev.h>
12 #include <linux/bio.h>
13 #include <linux/slab.h>
15 #define DM_MSG_PREFIX "striped"
17 struct stripe {
18 struct dm_dev *dev;
19 sector_t physical_start;
20 };
22 struct stripe_c {
23 uint32_t stripes;
25 /* The size of this target / num. stripes */
26 sector_t stripe_width;
28 /* stripe chunk size */
29 uint32_t chunk_shift;
30 sector_t chunk_mask;
32 struct stripe stripe[0];
33 };
35 static inline struct stripe_c *alloc_context(unsigned int stripes)
36 {
37 size_t len;
39 if (array_too_big(sizeof(struct stripe_c), sizeof(struct stripe),
40 stripes))
41 return NULL;
43 len = sizeof(struct stripe_c) + (sizeof(struct stripe) * stripes);
45 return kmalloc(len, GFP_KERNEL);
46 }
48 /*
49 * Parse a single <dev> <sector> pair
50 */
51 static int get_stripe(struct dm_target *ti, struct stripe_c *sc,
52 unsigned int stripe, char **argv)
53 {
54 unsigned long long start;
56 if (sscanf(argv[1], "%llu", &start) != 1)
57 return -EINVAL;
59 if (dm_get_device(ti, argv[0], start, sc->stripe_width,
60 dm_table_get_mode(ti->table),
61 &sc->stripe[stripe].dev))
62 return -ENXIO;
64 sc->stripe[stripe].physical_start = start;
65 return 0;
66 }
68 /*
69 * Construct a striped mapping.
70 * <number of stripes> <chunk size (2^^n)> [<dev_path> <offset>]+
71 */
72 static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv)
73 {
74 struct stripe_c *sc;
75 sector_t width;
76 uint32_t stripes;
77 uint32_t chunk_size;
78 char *end;
79 int r;
80 unsigned int i;
82 if (argc < 2) {
83 ti->error = "Not enough arguments";
84 return -EINVAL;
85 }
87 stripes = simple_strtoul(argv[0], &end, 10);
88 if (*end) {
89 ti->error = "Invalid stripe count";
90 return -EINVAL;
91 }
93 chunk_size = simple_strtoul(argv[1], &end, 10);
94 if (*end) {
95 ti->error = "Invalid chunk_size";
96 return -EINVAL;
97 }
99 /*
100 * chunk_size is a power of two
101 */
102 if (!chunk_size || (chunk_size & (chunk_size - 1)) ||
103 (chunk_size < (PAGE_SIZE >> SECTOR_SHIFT))) {
104 ti->error = "Invalid chunk size";
105 return -EINVAL;
106 }
108 if (ti->len & (chunk_size - 1)) {
109 ti->error = "Target length not divisible by "
110 "chunk size";
111 return -EINVAL;
112 }
114 width = ti->len;
115 if (sector_div(width, stripes)) {
116 ti->error = "Target length not divisible by "
117 "number of stripes";
118 return -EINVAL;
119 }
121 /*
122 * Do we have enough arguments for that many stripes ?
123 */
124 if (argc != (2 + 2 * stripes)) {
125 ti->error = "Not enough destinations "
126 "specified";
127 return -EINVAL;
128 }
130 sc = alloc_context(stripes);
131 if (!sc) {
132 ti->error = "Memory allocation for striped context "
133 "failed";
134 return -ENOMEM;
135 }
137 sc->stripes = stripes;
138 sc->stripe_width = width;
139 ti->split_io = chunk_size;
141 sc->chunk_mask = ((sector_t) chunk_size) - 1;
142 for (sc->chunk_shift = 0; chunk_size; sc->chunk_shift++)
143 chunk_size >>= 1;
144 sc->chunk_shift--;
146 /*
147 * Get the stripe destinations.
148 */
149 for (i = 0; i < stripes; i++) {
150 argv += 2;
152 r = get_stripe(ti, sc, i, argv);
153 if (r < 0) {
154 ti->error = "Couldn't parse stripe destination";
155 while (i--)
156 dm_put_device(ti, sc->stripe[i].dev);
157 kfree(sc);
158 return r;
159 }
160 }
162 ti->private = sc;
163 return 0;
164 }
166 static void stripe_dtr(struct dm_target *ti)
167 {
168 unsigned int i;
169 struct stripe_c *sc = (struct stripe_c *) ti->private;
171 for (i = 0; i < sc->stripes; i++)
172 dm_put_device(ti, sc->stripe[i].dev);
174 kfree(sc);
175 }
177 static int stripe_map(struct dm_target *ti, struct bio *bio,
178 union map_info *map_context)
179 {
180 struct stripe_c *sc = (struct stripe_c *) ti->private;
182 sector_t offset = bio->bi_sector - ti->begin;
183 sector_t chunk = offset >> sc->chunk_shift;
184 uint32_t stripe = sector_div(chunk, sc->stripes);
186 bio->bi_bdev = sc->stripe[stripe].dev->bdev;
187 bio->bi_sector = sc->stripe[stripe].physical_start +
188 (chunk << sc->chunk_shift) + (offset & sc->chunk_mask);
189 return 1;
190 }
192 static int stripe_status(struct dm_target *ti,
193 status_type_t type, char *result, unsigned int maxlen)
194 {
195 struct stripe_c *sc = (struct stripe_c *) ti->private;
196 unsigned int sz = 0;
197 unsigned int i;
199 switch (type) {
200 case STATUSTYPE_INFO:
201 result[0] = '\0';
202 break;
204 case STATUSTYPE_TABLE:
205 DMEMIT("%d %llu", sc->stripes,
206 (unsigned long long)sc->chunk_mask + 1);
207 for (i = 0; i < sc->stripes; i++)
208 DMEMIT(" %s %llu", sc->stripe[i].dev->name,
209 (unsigned long long)sc->stripe[i].physical_start);
210 break;
211 }
212 return 0;
213 }
215 static struct target_type stripe_target = {
216 .name = "striped",
217 .version= {1, 0, 2},
218 .module = THIS_MODULE,
219 .ctr = stripe_ctr,
220 .dtr = stripe_dtr,
221 .map = stripe_map,
222 .status = stripe_status,
223 };
225 int __init dm_stripe_init(void)
226 {
227 int r;
229 r = dm_register_target(&stripe_target);
230 if (r < 0)
231 DMWARN("target registration failed");
233 return r;
234 }
236 void dm_stripe_exit(void)
237 {
238 if (dm_unregister_target(&stripe_target))
239 DMWARN("target unregistration failed");
241 return;
242 }