ia64/linux-2.6.18-xen.hg

view scripts/mod/sumversion.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 105239038a17
children
line source
1 #include <netinet/in.h>
2 #ifdef __sun__
3 #include <inttypes.h>
4 #else
5 #include <stdint.h>
6 #endif
7 #include <ctype.h>
8 #include <errno.h>
9 #include <string.h>
10 #include <limits.h>
11 #include "modpost.h"
13 /*
14 * Stolen form Cryptographic API.
15 *
16 * MD4 Message Digest Algorithm (RFC1320).
17 *
18 * Implementation derived from Andrew Tridgell and Steve French's
19 * CIFS MD4 implementation, and the cryptoapi implementation
20 * originally based on the public domain implementation written
21 * by Colin Plumb in 1993.
22 *
23 * Copyright (c) Andrew Tridgell 1997-1998.
24 * Modified by Steve French (sfrench@us.ibm.com) 2002
25 * Copyright (c) Cryptoapi developers.
26 * Copyright (c) 2002 David S. Miller (davem@redhat.com)
27 * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
28 *
29 * This program is free software; you can redistribute it and/or modify
30 * it under the terms of the GNU General Public License as published by
31 * the Free Software Foundation; either version 2 of the License, or
32 * (at your option) any later version.
33 *
34 */
35 #define MD4_DIGEST_SIZE 16
36 #define MD4_HMAC_BLOCK_SIZE 64
37 #define MD4_BLOCK_WORDS 16
38 #define MD4_HASH_WORDS 4
40 struct md4_ctx {
41 uint32_t hash[MD4_HASH_WORDS];
42 uint32_t block[MD4_BLOCK_WORDS];
43 uint64_t byte_count;
44 };
46 static inline uint32_t lshift(uint32_t x, unsigned int s)
47 {
48 x &= 0xFFFFFFFF;
49 return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
50 }
52 static inline uint32_t F(uint32_t x, uint32_t y, uint32_t z)
53 {
54 return (x & y) | ((~x) & z);
55 }
57 static inline uint32_t G(uint32_t x, uint32_t y, uint32_t z)
58 {
59 return (x & y) | (x & z) | (y & z);
60 }
62 static inline uint32_t H(uint32_t x, uint32_t y, uint32_t z)
63 {
64 return x ^ y ^ z;
65 }
67 #define ROUND1(a,b,c,d,k,s) (a = lshift(a + F(b,c,d) + k, s))
68 #define ROUND2(a,b,c,d,k,s) (a = lshift(a + G(b,c,d) + k + (uint32_t)0x5A827999,s))
69 #define ROUND3(a,b,c,d,k,s) (a = lshift(a + H(b,c,d) + k + (uint32_t)0x6ED9EBA1,s))
71 /* XXX: this stuff can be optimized */
72 static inline void le32_to_cpu_array(uint32_t *buf, unsigned int words)
73 {
74 while (words--) {
75 *buf = ntohl(*buf);
76 buf++;
77 }
78 }
80 static inline void cpu_to_le32_array(uint32_t *buf, unsigned int words)
81 {
82 while (words--) {
83 *buf = htonl(*buf);
84 buf++;
85 }
86 }
88 static void md4_transform(uint32_t *hash, uint32_t const *in)
89 {
90 uint32_t a, b, c, d;
92 a = hash[0];
93 b = hash[1];
94 c = hash[2];
95 d = hash[3];
97 ROUND1(a, b, c, d, in[0], 3);
98 ROUND1(d, a, b, c, in[1], 7);
99 ROUND1(c, d, a, b, in[2], 11);
100 ROUND1(b, c, d, a, in[3], 19);
101 ROUND1(a, b, c, d, in[4], 3);
102 ROUND1(d, a, b, c, in[5], 7);
103 ROUND1(c, d, a, b, in[6], 11);
104 ROUND1(b, c, d, a, in[7], 19);
105 ROUND1(a, b, c, d, in[8], 3);
106 ROUND1(d, a, b, c, in[9], 7);
107 ROUND1(c, d, a, b, in[10], 11);
108 ROUND1(b, c, d, a, in[11], 19);
109 ROUND1(a, b, c, d, in[12], 3);
110 ROUND1(d, a, b, c, in[13], 7);
111 ROUND1(c, d, a, b, in[14], 11);
112 ROUND1(b, c, d, a, in[15], 19);
114 ROUND2(a, b, c, d,in[ 0], 3);
115 ROUND2(d, a, b, c, in[4], 5);
116 ROUND2(c, d, a, b, in[8], 9);
117 ROUND2(b, c, d, a, in[12], 13);
118 ROUND2(a, b, c, d, in[1], 3);
119 ROUND2(d, a, b, c, in[5], 5);
120 ROUND2(c, d, a, b, in[9], 9);
121 ROUND2(b, c, d, a, in[13], 13);
122 ROUND2(a, b, c, d, in[2], 3);
123 ROUND2(d, a, b, c, in[6], 5);
124 ROUND2(c, d, a, b, in[10], 9);
125 ROUND2(b, c, d, a, in[14], 13);
126 ROUND2(a, b, c, d, in[3], 3);
127 ROUND2(d, a, b, c, in[7], 5);
128 ROUND2(c, d, a, b, in[11], 9);
129 ROUND2(b, c, d, a, in[15], 13);
131 ROUND3(a, b, c, d,in[ 0], 3);
132 ROUND3(d, a, b, c, in[8], 9);
133 ROUND3(c, d, a, b, in[4], 11);
134 ROUND3(b, c, d, a, in[12], 15);
135 ROUND3(a, b, c, d, in[2], 3);
136 ROUND3(d, a, b, c, in[10], 9);
137 ROUND3(c, d, a, b, in[6], 11);
138 ROUND3(b, c, d, a, in[14], 15);
139 ROUND3(a, b, c, d, in[1], 3);
140 ROUND3(d, a, b, c, in[9], 9);
141 ROUND3(c, d, a, b, in[5], 11);
142 ROUND3(b, c, d, a, in[13], 15);
143 ROUND3(a, b, c, d, in[3], 3);
144 ROUND3(d, a, b, c, in[11], 9);
145 ROUND3(c, d, a, b, in[7], 11);
146 ROUND3(b, c, d, a, in[15], 15);
148 hash[0] += a;
149 hash[1] += b;
150 hash[2] += c;
151 hash[3] += d;
152 }
154 static inline void md4_transform_helper(struct md4_ctx *ctx)
155 {
156 le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(uint32_t));
157 md4_transform(ctx->hash, ctx->block);
158 }
160 static void md4_init(struct md4_ctx *mctx)
161 {
162 mctx->hash[0] = 0x67452301;
163 mctx->hash[1] = 0xefcdab89;
164 mctx->hash[2] = 0x98badcfe;
165 mctx->hash[3] = 0x10325476;
166 mctx->byte_count = 0;
167 }
169 static void md4_update(struct md4_ctx *mctx,
170 const unsigned char *data, unsigned int len)
171 {
172 const uint32_t avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
174 mctx->byte_count += len;
176 if (avail > len) {
177 memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
178 data, len);
179 return;
180 }
182 memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
183 data, avail);
185 md4_transform_helper(mctx);
186 data += avail;
187 len -= avail;
189 while (len >= sizeof(mctx->block)) {
190 memcpy(mctx->block, data, sizeof(mctx->block));
191 md4_transform_helper(mctx);
192 data += sizeof(mctx->block);
193 len -= sizeof(mctx->block);
194 }
196 memcpy(mctx->block, data, len);
197 }
199 static void md4_final_ascii(struct md4_ctx *mctx, char *out, unsigned int len)
200 {
201 const unsigned int offset = mctx->byte_count & 0x3f;
202 char *p = (char *)mctx->block + offset;
203 int padding = 56 - (offset + 1);
205 *p++ = 0x80;
206 if (padding < 0) {
207 memset(p, 0x00, padding + sizeof (uint64_t));
208 md4_transform_helper(mctx);
209 p = (char *)mctx->block;
210 padding = 56;
211 }
213 memset(p, 0, padding);
214 mctx->block[14] = mctx->byte_count << 3;
215 mctx->block[15] = mctx->byte_count >> 29;
216 le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
217 sizeof(uint64_t)) / sizeof(uint32_t));
218 md4_transform(mctx->hash, mctx->block);
219 cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(uint32_t));
221 snprintf(out, len, "%08X%08X%08X%08X",
222 mctx->hash[0], mctx->hash[1], mctx->hash[2], mctx->hash[3]);
223 }
225 static inline void add_char(unsigned char c, struct md4_ctx *md)
226 {
227 md4_update(md, &c, 1);
228 }
230 static int parse_string(const char *file, unsigned long len,
231 struct md4_ctx *md)
232 {
233 unsigned long i;
235 add_char(file[0], md);
236 for (i = 1; i < len; i++) {
237 add_char(file[i], md);
238 if (file[i] == '"' && file[i-1] != '\\')
239 break;
240 }
241 return i;
242 }
244 static int parse_comment(const char *file, unsigned long len)
245 {
246 unsigned long i;
248 for (i = 2; i < len; i++) {
249 if (file[i-1] == '*' && file[i] == '/')
250 break;
251 }
252 return i;
253 }
255 /* FIXME: Handle .s files differently (eg. # starts comments) --RR */
256 static int parse_file(const char *fname, struct md4_ctx *md)
257 {
258 char *file;
259 unsigned long i, len;
261 file = grab_file(fname, &len);
262 if (!file)
263 return 0;
265 for (i = 0; i < len; i++) {
266 /* Collapse and ignore \ and CR. */
267 if (file[i] == '\\' && (i+1 < len) && file[i+1] == '\n') {
268 i++;
269 continue;
270 }
272 /* Ignore whitespace */
273 if (isspace(file[i]))
274 continue;
276 /* Handle strings as whole units */
277 if (file[i] == '"') {
278 i += parse_string(file+i, len - i, md);
279 continue;
280 }
282 /* Comments: ignore */
283 if (file[i] == '/' && file[i+1] == '*') {
284 i += parse_comment(file+i, len - i);
285 continue;
286 }
288 add_char(file[i], md);
289 }
290 release_file(file, len);
291 return 1;
292 }
294 /* We have dir/file.o. Open dir/.file.o.cmd, look for deps_ line to
295 * figure out source file. */
296 static int parse_source_files(const char *objfile, struct md4_ctx *md)
297 {
298 char *cmd, *file, *line, *dir;
299 const char *base;
300 unsigned long flen, pos = 0;
301 int dirlen, ret = 0, check_files = 0;
303 cmd = NOFAIL(malloc(strlen(objfile) + sizeof("..cmd")));
305 base = strrchr(objfile, '/');
306 if (base) {
307 base++;
308 dirlen = base - objfile;
309 sprintf(cmd, "%.*s.%s.cmd", dirlen, objfile, base);
310 } else {
311 dirlen = 0;
312 sprintf(cmd, ".%s.cmd", objfile);
313 }
314 dir = NOFAIL(malloc(dirlen + 1));
315 strncpy(dir, objfile, dirlen);
316 dir[dirlen] = '\0';
318 file = grab_file(cmd, &flen);
319 if (!file) {
320 warn("could not find %s for %s\n", cmd, objfile);
321 goto out;
322 }
324 /* There will be a line like so:
325 deps_drivers/net/dummy.o := \
326 drivers/net/dummy.c \
327 $(wildcard include/config/net/fastroute.h) \
328 include/linux/config.h \
329 $(wildcard include/config/h.h) \
330 include/linux/module.h \
332 Sum all files in the same dir or subdirs.
333 */
334 while ((line = get_next_line(&pos, file, flen)) != NULL) {
335 char* p = line;
336 if (strncmp(line, "deps_", sizeof("deps_")-1) == 0) {
337 check_files = 1;
338 continue;
339 }
340 if (!check_files)
341 continue;
343 /* Continue until line does not end with '\' */
344 if ( *(p + strlen(p)-1) != '\\')
345 break;
346 /* Terminate line at first space, to get rid of final ' \' */
347 while (*p) {
348 if (isspace(*p)) {
349 *p = '\0';
350 break;
351 }
352 p++;
353 }
355 /* Check if this file is in same dir as objfile */
356 if ((strstr(line, dir)+strlen(dir)-1) == strrchr(line, '/')) {
357 if (!parse_file(line, md)) {
358 warn("could not open %s: %s\n",
359 line, strerror(errno));
360 goto out_file;
361 }
363 }
365 }
367 /* Everyone parsed OK */
368 ret = 1;
369 out_file:
370 release_file(file, flen);
371 out:
372 free(dir);
373 free(cmd);
374 return ret;
375 }
377 /* Calc and record src checksum. */
378 void get_src_version(const char *modname, char sum[], unsigned sumlen)
379 {
380 void *file;
381 unsigned long len;
382 struct md4_ctx md;
383 char *sources, *end, *fname;
384 const char *basename;
385 char filelist[PATH_MAX + 1];
386 char *modverdir = getenv("MODVERDIR");
388 if (!modverdir)
389 modverdir = ".";
391 /* Source files for module are in .tmp_versions/modname.mod,
392 after the first line. */
393 if (strrchr(modname, '/'))
394 basename = strrchr(modname, '/') + 1;
395 else
396 basename = modname;
397 sprintf(filelist, "%s/%.*s.mod", modverdir,
398 (int) strlen(basename) - 2, basename);
400 file = grab_file(filelist, &len);
401 if (!file) {
402 warn("could not find versions for %s\n", filelist);
403 return;
404 }
406 sources = strchr(file, '\n');
407 if (!sources) {
408 warn("malformed versions file for %s\n", modname);
409 goto release;
410 }
412 sources++;
413 end = strchr(sources, '\n');
414 if (!end) {
415 warn("bad ending versions file for %s\n", modname);
416 goto release;
417 }
418 *end = '\0';
420 md4_init(&md);
421 while ((fname = strsep(&sources, " ")) != NULL) {
422 if (!*fname)
423 continue;
424 if (!parse_source_files(fname, &md))
425 goto release;
426 }
428 md4_final_ascii(&md, sum, sumlen);
429 release:
430 release_file(file, len);
431 }
433 static void write_version(const char *filename, const char *sum,
434 unsigned long offset)
435 {
436 int fd;
438 fd = open(filename, O_RDWR);
439 if (fd < 0) {
440 warn("changing sum in %s failed: %s\n",
441 filename, strerror(errno));
442 return;
443 }
445 if (lseek(fd, offset, SEEK_SET) == (off_t)-1) {
446 warn("changing sum in %s:%lu failed: %s\n",
447 filename, offset, strerror(errno));
448 goto out;
449 }
451 if (write(fd, sum, strlen(sum)+1) != strlen(sum)+1) {
452 warn("writing sum in %s failed: %s\n",
453 filename, strerror(errno));
454 goto out;
455 }
456 out:
457 close(fd);
458 }
460 static int strip_rcs_crap(char *version)
461 {
462 unsigned int len, full_len;
464 if (strncmp(version, "$Revision", strlen("$Revision")) != 0)
465 return 0;
467 /* Space for version string follows. */
468 full_len = strlen(version) + strlen(version + strlen(version) + 1) + 2;
470 /* Move string to start with version number: prefix will be
471 * $Revision$ or $Revision: */
472 len = strlen("$Revision");
473 if (version[len] == ':' || version[len] == '$')
474 len++;
475 while (isspace(version[len]))
476 len++;
477 memmove(version, version+len, full_len-len);
478 full_len -= len;
480 /* Preserve up to next whitespace. */
481 len = 0;
482 while (version[len] && !isspace(version[len]))
483 len++;
484 memmove(version + len, version + strlen(version),
485 full_len - strlen(version));
486 return 1;
487 }
489 /* Clean up RCS-style version numbers. */
490 void maybe_frob_rcs_version(const char *modfilename,
491 char *version,
492 void *modinfo,
493 unsigned long version_offset)
494 {
495 if (strip_rcs_crap(version))
496 write_version(modfilename, version, version_offset);
497 }