ia64/linux-2.6.18-xen.hg

view usr/gen_init_cpio.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 #include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <string.h>
6 #include <unistd.h>
7 #include <time.h>
8 #include <fcntl.h>
9 #include <errno.h>
10 #include <ctype.h>
11 #include <limits.h>
13 /*
14 * Original work by Jeff Garzik
15 *
16 * External file lists, symlink, pipe and fifo support by Thayne Harbaugh
17 */
19 #define xstr(s) #s
20 #define str(s) xstr(s)
22 static unsigned int offset;
23 static unsigned int ino = 721;
25 struct file_handler {
26 const char *type;
27 int (*handler)(const char *line);
28 };
30 static void push_string(const char *name)
31 {
32 unsigned int name_len = strlen(name) + 1;
34 fputs(name, stdout);
35 putchar(0);
36 offset += name_len;
37 }
39 static void push_pad (void)
40 {
41 while (offset & 3) {
42 putchar(0);
43 offset++;
44 }
45 }
47 static void push_rest(const char *name)
48 {
49 unsigned int name_len = strlen(name) + 1;
50 unsigned int tmp_ofs;
52 fputs(name, stdout);
53 putchar(0);
54 offset += name_len;
56 tmp_ofs = name_len + 110;
57 while (tmp_ofs & 3) {
58 putchar(0);
59 offset++;
60 tmp_ofs++;
61 }
62 }
64 static void push_hdr(const char *s)
65 {
66 fputs(s, stdout);
67 offset += 110;
68 }
70 static void cpio_trailer(void)
71 {
72 char s[256];
73 const char name[] = "TRAILER!!!";
75 sprintf(s, "%s%08X%08X%08lX%08lX%08X%08lX"
76 "%08X%08X%08X%08X%08X%08X%08X",
77 "070701", /* magic */
78 0, /* ino */
79 0, /* mode */
80 (long) 0, /* uid */
81 (long) 0, /* gid */
82 1, /* nlink */
83 (long) 0, /* mtime */
84 0, /* filesize */
85 0, /* major */
86 0, /* minor */
87 0, /* rmajor */
88 0, /* rminor */
89 (unsigned)strlen(name)+1, /* namesize */
90 0); /* chksum */
91 push_hdr(s);
92 push_rest(name);
94 while (offset % 512) {
95 putchar(0);
96 offset++;
97 }
98 }
100 static int cpio_mkslink(const char *name, const char *target,
101 unsigned int mode, uid_t uid, gid_t gid)
102 {
103 char s[256];
104 time_t mtime = time(NULL);
106 sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
107 "%08X%08X%08X%08X%08X%08X%08X",
108 "070701", /* magic */
109 ino++, /* ino */
110 S_IFLNK | mode, /* mode */
111 (long) uid, /* uid */
112 (long) gid, /* gid */
113 1, /* nlink */
114 (long) mtime, /* mtime */
115 (unsigned)strlen(target)+1, /* filesize */
116 3, /* major */
117 1, /* minor */
118 0, /* rmajor */
119 0, /* rminor */
120 (unsigned)strlen(name) + 1,/* namesize */
121 0); /* chksum */
122 push_hdr(s);
123 push_string(name);
124 push_pad();
125 push_string(target);
126 push_pad();
127 return 0;
128 }
130 static int cpio_mkslink_line(const char *line)
131 {
132 char name[PATH_MAX + 1];
133 char target[PATH_MAX + 1];
134 unsigned int mode;
135 int uid;
136 int gid;
137 int rc = -1;
139 if (5 != sscanf(line, "%" str(PATH_MAX) "s %" str(PATH_MAX) "s %o %d %d", name, target, &mode, &uid, &gid)) {
140 fprintf(stderr, "Unrecognized dir format '%s'", line);
141 goto fail;
142 }
143 rc = cpio_mkslink(name, target, mode, uid, gid);
144 fail:
145 return rc;
146 }
148 static int cpio_mkgeneric(const char *name, unsigned int mode,
149 uid_t uid, gid_t gid)
150 {
151 char s[256];
152 time_t mtime = time(NULL);
154 sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
155 "%08X%08X%08X%08X%08X%08X%08X",
156 "070701", /* magic */
157 ino++, /* ino */
158 mode, /* mode */
159 (long) uid, /* uid */
160 (long) gid, /* gid */
161 2, /* nlink */
162 (long) mtime, /* mtime */
163 0, /* filesize */
164 3, /* major */
165 1, /* minor */
166 0, /* rmajor */
167 0, /* rminor */
168 (unsigned)strlen(name) + 1,/* namesize */
169 0); /* chksum */
170 push_hdr(s);
171 push_rest(name);
172 return 0;
173 }
175 enum generic_types {
176 GT_DIR,
177 GT_PIPE,
178 GT_SOCK
179 };
181 struct generic_type {
182 const char *type;
183 mode_t mode;
184 };
186 static struct generic_type generic_type_table[] = {
187 [GT_DIR] = {
188 .type = "dir",
189 .mode = S_IFDIR
190 },
191 [GT_PIPE] = {
192 .type = "pipe",
193 .mode = S_IFIFO
194 },
195 [GT_SOCK] = {
196 .type = "sock",
197 .mode = S_IFSOCK
198 }
199 };
201 static int cpio_mkgeneric_line(const char *line, enum generic_types gt)
202 {
203 char name[PATH_MAX + 1];
204 unsigned int mode;
205 int uid;
206 int gid;
207 int rc = -1;
209 if (4 != sscanf(line, "%" str(PATH_MAX) "s %o %d %d", name, &mode, &uid, &gid)) {
210 fprintf(stderr, "Unrecognized %s format '%s'",
211 line, generic_type_table[gt].type);
212 goto fail;
213 }
214 mode |= generic_type_table[gt].mode;
215 rc = cpio_mkgeneric(name, mode, uid, gid);
216 fail:
217 return rc;
218 }
220 static int cpio_mkdir_line(const char *line)
221 {
222 return cpio_mkgeneric_line(line, GT_DIR);
223 }
225 static int cpio_mkpipe_line(const char *line)
226 {
227 return cpio_mkgeneric_line(line, GT_PIPE);
228 }
230 static int cpio_mksock_line(const char *line)
231 {
232 return cpio_mkgeneric_line(line, GT_SOCK);
233 }
235 static int cpio_mknod(const char *name, unsigned int mode,
236 uid_t uid, gid_t gid, char dev_type,
237 unsigned int maj, unsigned int min)
238 {
239 char s[256];
240 time_t mtime = time(NULL);
242 if (dev_type == 'b')
243 mode |= S_IFBLK;
244 else
245 mode |= S_IFCHR;
247 sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
248 "%08X%08X%08X%08X%08X%08X%08X",
249 "070701", /* magic */
250 ino++, /* ino */
251 mode, /* mode */
252 (long) uid, /* uid */
253 (long) gid, /* gid */
254 1, /* nlink */
255 (long) mtime, /* mtime */
256 0, /* filesize */
257 3, /* major */
258 1, /* minor */
259 maj, /* rmajor */
260 min, /* rminor */
261 (unsigned)strlen(name) + 1,/* namesize */
262 0); /* chksum */
263 push_hdr(s);
264 push_rest(name);
265 return 0;
266 }
268 static int cpio_mknod_line(const char *line)
269 {
270 char name[PATH_MAX + 1];
271 unsigned int mode;
272 int uid;
273 int gid;
274 char dev_type;
275 unsigned int maj;
276 unsigned int min;
277 int rc = -1;
279 if (7 != sscanf(line, "%" str(PATH_MAX) "s %o %d %d %c %u %u",
280 name, &mode, &uid, &gid, &dev_type, &maj, &min)) {
281 fprintf(stderr, "Unrecognized nod format '%s'", line);
282 goto fail;
283 }
284 rc = cpio_mknod(name, mode, uid, gid, dev_type, maj, min);
285 fail:
286 return rc;
287 }
289 /* Not marked static to keep the compiler quiet, as no one uses this yet... */
290 static int cpio_mkfile(const char *name, const char *location,
291 unsigned int mode, uid_t uid, gid_t gid)
292 {
293 char s[256];
294 char *filebuf = NULL;
295 struct stat buf;
296 int file = -1;
297 int retval;
298 int rc = -1;
300 mode |= S_IFREG;
302 retval = stat (location, &buf);
303 if (retval) {
304 fprintf (stderr, "File %s could not be located\n", location);
305 goto error;
306 }
308 file = open (location, O_RDONLY);
309 if (file < 0) {
310 fprintf (stderr, "File %s could not be opened for reading\n", location);
311 goto error;
312 }
314 filebuf = malloc(buf.st_size);
315 if (!filebuf) {
316 fprintf (stderr, "out of memory\n");
317 goto error;
318 }
320 retval = read (file, filebuf, buf.st_size);
321 if (retval < 0) {
322 fprintf (stderr, "Can not read %s file\n", location);
323 goto error;
324 }
326 sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
327 "%08X%08X%08X%08X%08X%08X%08X",
328 "070701", /* magic */
329 ino++, /* ino */
330 mode, /* mode */
331 (long) uid, /* uid */
332 (long) gid, /* gid */
333 1, /* nlink */
334 (long) buf.st_mtime, /* mtime */
335 (int) buf.st_size, /* filesize */
336 3, /* major */
337 1, /* minor */
338 0, /* rmajor */
339 0, /* rminor */
340 (unsigned)strlen(name) + 1,/* namesize */
341 0); /* chksum */
342 push_hdr(s);
343 push_string(name);
344 push_pad();
346 fwrite(filebuf, buf.st_size, 1, stdout);
347 offset += buf.st_size;
348 push_pad();
349 rc = 0;
351 error:
352 if (filebuf) free(filebuf);
353 if (file >= 0) close(file);
354 return rc;
355 }
357 static int cpio_mkfile_line(const char *line)
358 {
359 char name[PATH_MAX + 1];
360 char location[PATH_MAX + 1];
361 unsigned int mode;
362 int uid;
363 int gid;
364 int rc = -1;
366 if (5 != sscanf(line, "%" str(PATH_MAX) "s %" str(PATH_MAX) "s %o %d %d", name, location, &mode, &uid, &gid)) {
367 fprintf(stderr, "Unrecognized file format '%s'", line);
368 goto fail;
369 }
370 rc = cpio_mkfile(name, location, mode, uid, gid);
371 fail:
372 return rc;
373 }
375 void usage(const char *prog)
376 {
377 fprintf(stderr, "Usage:\n"
378 "\t%s <cpio_list>\n"
379 "\n"
380 "<cpio_list> is a file containing newline separated entries that\n"
381 "describe the files to be included in the initramfs archive:\n"
382 "\n"
383 "# a comment\n"
384 "file <name> <location> <mode> <uid> <gid>\n"
385 "dir <name> <mode> <uid> <gid>\n"
386 "nod <name> <mode> <uid> <gid> <dev_type> <maj> <min>\n"
387 "slink <name> <target> <mode> <uid> <gid>\n"
388 "pipe <name> <mode> <uid> <gid>\n"
389 "sock <name> <mode> <uid> <gid>\n"
390 "\n"
391 "<name> name of the file/dir/nod/etc in the archive\n"
392 "<location> location of the file in the current filesystem\n"
393 "<target> link target\n"
394 "<mode> mode/permissions of the file\n"
395 "<uid> user id (0=root)\n"
396 "<gid> group id (0=root)\n"
397 "<dev_type> device type (b=block, c=character)\n"
398 "<maj> major number of nod\n"
399 "<min> minor number of nod\n"
400 "\n"
401 "example:\n"
402 "# A simple initramfs\n"
403 "dir /dev 0755 0 0\n"
404 "nod /dev/console 0600 0 0 c 5 1\n"
405 "dir /root 0700 0 0\n"
406 "dir /sbin 0755 0 0\n"
407 "file /sbin/kinit /usr/src/klibc/kinit/kinit 0755 0 0\n",
408 prog);
409 }
411 struct file_handler file_handler_table[] = {
412 {
413 .type = "file",
414 .handler = cpio_mkfile_line,
415 }, {
416 .type = "nod",
417 .handler = cpio_mknod_line,
418 }, {
419 .type = "dir",
420 .handler = cpio_mkdir_line,
421 }, {
422 .type = "slink",
423 .handler = cpio_mkslink_line,
424 }, {
425 .type = "pipe",
426 .handler = cpio_mkpipe_line,
427 }, {
428 .type = "sock",
429 .handler = cpio_mksock_line,
430 }, {
431 .type = NULL,
432 .handler = NULL,
433 }
434 };
436 #define LINE_SIZE (2 * PATH_MAX + 50)
438 int main (int argc, char *argv[])
439 {
440 FILE *cpio_list;
441 char line[LINE_SIZE];
442 char *args, *type;
443 int ec = 0;
444 int line_nr = 0;
446 if (2 != argc) {
447 usage(argv[0]);
448 exit(1);
449 }
451 if (! (cpio_list = fopen(argv[1], "r"))) {
452 fprintf(stderr, "ERROR: unable to open '%s': %s\n\n",
453 argv[1], strerror(errno));
454 usage(argv[0]);
455 exit(1);
456 }
458 while (fgets(line, LINE_SIZE, cpio_list)) {
459 int type_idx;
460 size_t slen = strlen(line);
462 line_nr++;
464 if ('#' == *line) {
465 /* comment - skip to next line */
466 continue;
467 }
469 if (! (type = strtok(line, " \t"))) {
470 fprintf(stderr,
471 "ERROR: incorrect format, could not locate file type line %d: '%s'\n",
472 line_nr, line);
473 ec = -1;
474 break;
475 }
477 if ('\n' == *type) {
478 /* a blank line */
479 continue;
480 }
482 if (slen == strlen(type)) {
483 /* must be an empty line */
484 continue;
485 }
487 if (! (args = strtok(NULL, "\n"))) {
488 fprintf(stderr,
489 "ERROR: incorrect format, newline required line %d: '%s'\n",
490 line_nr, line);
491 ec = -1;
492 }
494 for (type_idx = 0; file_handler_table[type_idx].type; type_idx++) {
495 int rc;
496 if (! strcmp(line, file_handler_table[type_idx].type)) {
497 if ((rc = file_handler_table[type_idx].handler(args))) {
498 ec = rc;
499 fprintf(stderr, " line %d\n", line_nr);
500 }
501 break;
502 }
503 }
505 if (NULL == file_handler_table[type_idx].type) {
506 fprintf(stderr, "unknown file type line %d: '%s'\n",
507 line_nr, line);
508 }
509 }
510 if (ec == 0)
511 cpio_trailer();
513 exit(ec);
514 }