ia64/linux-2.6.18-xen.hg

view scripts/basic/docproc.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 * docproc is a simple preprocessor for the template files
3 * used as placeholders for the kernel internal documentation.
4 * docproc is used for documentation-frontend and
5 * dependency-generator.
6 * The two usages have in common that they require
7 * some knowledge of the .tmpl syntax, therefore they
8 * are kept together.
9 *
10 * documentation-frontend
11 * Scans the template file and call kernel-doc for
12 * all occurrences of ![EIF]file
13 * Beforehand each referenced file are scanned for
14 * any exported sympols "EXPORT_SYMBOL()" statements.
15 * This is used to create proper -function and
16 * -nofunction arguments in calls to kernel-doc.
17 * Usage: docproc doc file.tmpl
18 *
19 * dependency-generator:
20 * Scans the template file and list all files
21 * referenced in a format recognized by make.
22 * Usage: docproc depend file.tmpl
23 * Writes dependency information to stdout
24 * in the following format:
25 * file.tmpl src.c src2.c
26 * The filenames are obtained from the following constructs:
27 * !Efilename
28 * !Ifilename
29 * !Dfilename
30 * !Ffilename
31 *
32 */
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include <unistd.h>
39 #include <limits.h>
40 #include <sys/types.h>
41 #include <sys/wait.h>
43 /* exitstatus is used to keep track of any failing calls to kernel-doc,
44 * but execution continues. */
45 int exitstatus = 0;
47 typedef void DFL(char *);
48 DFL *defaultline;
50 typedef void FILEONLY(char * file);
51 FILEONLY *internalfunctions;
52 FILEONLY *externalfunctions;
53 FILEONLY *symbolsonly;
55 typedef void FILELINE(char * file, char * line);
56 FILELINE * singlefunctions;
57 FILELINE * entity_system;
59 #define MAXLINESZ 2048
60 #define MAXFILES 250
61 #define KERNELDOCPATH "scripts/"
62 #define KERNELDOC "kernel-doc"
63 #define DOCBOOK "-docbook"
64 #define FUNCTION "-function"
65 #define NOFUNCTION "-nofunction"
67 void usage (void)
68 {
69 fprintf(stderr, "Usage: docproc {doc|depend} file\n");
70 fprintf(stderr, "Input is read from file.tmpl. Output is sent to stdout\n");
71 fprintf(stderr, "doc: frontend when generating kernel documentation\n");
72 fprintf(stderr, "depend: generate list of files referenced within file\n");
73 }
75 /*
76 * Execute kernel-doc with parameters givin in svec
77 */
78 void exec_kernel_doc(char **svec)
79 {
80 pid_t pid;
81 int ret;
82 char real_filename[PATH_MAX + 1];
83 /* Make sure output generated so far are flushed */
84 fflush(stdout);
85 switch(pid=fork()) {
86 case -1:
87 perror("fork");
88 exit(1);
89 case 0:
90 memset(real_filename, 0, sizeof(real_filename));
91 strncat(real_filename, getenv("SRCTREE"), PATH_MAX);
92 strncat(real_filename, KERNELDOCPATH KERNELDOC,
93 PATH_MAX - strlen(real_filename));
94 execvp(real_filename, svec);
95 fprintf(stderr, "exec ");
96 perror(real_filename);
97 exit(1);
98 default:
99 waitpid(pid, &ret ,0);
100 }
101 if (WIFEXITED(ret))
102 exitstatus |= WEXITSTATUS(ret);
103 else
104 exitstatus = 0xff;
105 }
107 /* Types used to create list of all exported symbols in a number of files */
108 struct symbols
109 {
110 char *name;
111 };
113 struct symfile
114 {
115 char *filename;
116 struct symbols *symbollist;
117 int symbolcnt;
118 };
120 struct symfile symfilelist[MAXFILES];
121 int symfilecnt = 0;
123 void add_new_symbol(struct symfile *sym, char * symname)
124 {
125 sym->symbollist =
126 realloc(sym->symbollist, (sym->symbolcnt + 1) * sizeof(char *));
127 sym->symbollist[sym->symbolcnt++].name = strdup(symname);
128 }
130 /* Add a filename to the list */
131 struct symfile * add_new_file(char * filename)
132 {
133 symfilelist[symfilecnt++].filename = strdup(filename);
134 return &symfilelist[symfilecnt - 1];
135 }
136 /* Check if file already are present in the list */
137 struct symfile * filename_exist(char * filename)
138 {
139 int i;
140 for (i=0; i < symfilecnt; i++)
141 if (strcmp(symfilelist[i].filename, filename) == 0)
142 return &symfilelist[i];
143 return NULL;
144 }
146 /*
147 * List all files referenced within the template file.
148 * Files are separated by tabs.
149 */
150 void adddep(char * file) { printf("\t%s", file); }
151 void adddep2(char * file, char * line) { line = line; adddep(file); }
152 void noaction(char * line) { line = line; }
153 void noaction2(char * file, char * line) { file = file; line = line; }
155 /* Echo the line without further action */
156 void printline(char * line) { printf("%s", line); }
158 /*
159 * Find all symbols exported with EXPORT_SYMBOL and EXPORT_SYMBOL_GPL
160 * in filename.
161 * All symbols located are stored in symfilelist.
162 */
163 void find_export_symbols(char * filename)
164 {
165 FILE * fp;
166 struct symfile *sym;
167 char line[MAXLINESZ];
168 if (filename_exist(filename) == NULL) {
169 char real_filename[PATH_MAX + 1];
170 memset(real_filename, 0, sizeof(real_filename));
171 strncat(real_filename, getenv("SRCTREE"), PATH_MAX);
172 strncat(real_filename, filename,
173 PATH_MAX - strlen(real_filename));
174 sym = add_new_file(filename);
175 fp = fopen(real_filename, "r");
176 if (fp == NULL)
177 {
178 fprintf(stderr, "docproc: ");
179 perror(real_filename);
180 }
181 while(fgets(line, MAXLINESZ, fp)) {
182 char *p;
183 char *e;
184 if (((p = strstr(line, "EXPORT_SYMBOL_GPL")) != 0) ||
185 ((p = strstr(line, "EXPORT_SYMBOL")) != 0)) {
186 /* Skip EXPORT_SYMBOL{_GPL} */
187 while (isalnum(*p) || *p == '_')
188 p++;
189 /* Remove paranteses and additional ws */
190 while (isspace(*p))
191 p++;
192 if (*p != '(')
193 continue; /* Syntax error? */
194 else
195 p++;
196 while (isspace(*p))
197 p++;
198 e = p;
199 while (isalnum(*e) || *e == '_')
200 e++;
201 *e = '\0';
202 add_new_symbol(sym, p);
203 }
204 }
205 fclose(fp);
206 }
207 }
209 /*
210 * Document all external or internal functions in a file.
211 * Call kernel-doc with following parameters:
212 * kernel-doc -docbook -nofunction function_name1 filename
213 * function names are obtained from all the the src files
214 * by find_export_symbols.
215 * intfunc uses -nofunction
216 * extfunc uses -function
217 */
218 void docfunctions(char * filename, char * type)
219 {
220 int i,j;
221 int symcnt = 0;
222 int idx = 0;
223 char **vec;
225 for (i=0; i <= symfilecnt; i++)
226 symcnt += symfilelist[i].symbolcnt;
227 vec = malloc((2 + 2 * symcnt + 2) * sizeof(char*));
228 if (vec == NULL) {
229 perror("docproc: ");
230 exit(1);
231 }
232 vec[idx++] = KERNELDOC;
233 vec[idx++] = DOCBOOK;
234 for (i=0; i < symfilecnt; i++) {
235 struct symfile * sym = &symfilelist[i];
236 for (j=0; j < sym->symbolcnt; j++) {
237 vec[idx++] = type;
238 vec[idx++] = sym->symbollist[j].name;
239 }
240 }
241 vec[idx++] = filename;
242 vec[idx] = NULL;
243 printf("<!-- %s -->\n", filename);
244 exec_kernel_doc(vec);
245 fflush(stdout);
246 free(vec);
247 }
248 void intfunc(char * filename) { docfunctions(filename, NOFUNCTION); }
249 void extfunc(char * filename) { docfunctions(filename, FUNCTION); }
251 /*
252 * Document spåecific function(s) in a file.
253 * Call kernel-doc with the following parameters:
254 * kernel-doc -docbook -function function1 [-function function2]
255 */
256 void singfunc(char * filename, char * line)
257 {
258 char *vec[200]; /* Enough for specific functions */
259 int i, idx = 0;
260 int startofsym = 1;
261 vec[idx++] = KERNELDOC;
262 vec[idx++] = DOCBOOK;
264 /* Split line up in individual parameters preceeded by FUNCTION */
265 for (i=0; line[i]; i++) {
266 if (isspace(line[i])) {
267 line[i] = '\0';
268 startofsym = 1;
269 continue;
270 }
271 if (startofsym) {
272 startofsym = 0;
273 vec[idx++] = FUNCTION;
274 vec[idx++] = &line[i];
275 }
276 }
277 vec[idx++] = filename;
278 vec[idx] = NULL;
279 exec_kernel_doc(vec);
280 }
282 /*
283 * Parse file, calling action specific functions for:
284 * 1) Lines containing !E
285 * 2) Lines containing !I
286 * 3) Lines containing !D
287 * 4) Lines containing !F
288 * 5) Default lines - lines not matching the above
289 */
290 void parse_file(FILE *infile)
291 {
292 char line[MAXLINESZ];
293 char * s;
294 while(fgets(line, MAXLINESZ, infile)) {
295 if (line[0] == '!') {
296 s = line + 2;
297 switch (line[1]) {
298 case 'E':
299 while (*s && !isspace(*s)) s++;
300 *s = '\0';
301 externalfunctions(line+2);
302 break;
303 case 'I':
304 while (*s && !isspace(*s)) s++;
305 *s = '\0';
306 internalfunctions(line+2);
307 break;
308 case 'D':
309 while (*s && !isspace(*s)) s++;
310 *s = '\0';
311 symbolsonly(line+2);
312 break;
313 case 'F':
314 /* filename */
315 while (*s && !isspace(*s)) s++;
316 *s++ = '\0';
317 /* function names */
318 while (isspace(*s))
319 s++;
320 singlefunctions(line +2, s);
321 break;
322 default:
323 defaultline(line);
324 }
325 }
326 else {
327 defaultline(line);
328 }
329 }
330 fflush(stdout);
331 }
334 int main(int argc, char *argv[])
335 {
336 FILE * infile;
337 if (argc != 3) {
338 usage();
339 exit(1);
340 }
341 /* Open file, exit on error */
342 infile = fopen(argv[2], "r");
343 if (infile == NULL) {
344 fprintf(stderr, "docproc: ");
345 perror(argv[2]);
346 exit(2);
347 }
349 if (strcmp("doc", argv[1]) == 0)
350 {
351 /* Need to do this in two passes.
352 * First pass is used to collect all symbols exported
353 * in the various files.
354 * Second pass generate the documentation.
355 * This is required because function are declared
356 * and exported in different files :-((
357 */
358 /* Collect symbols */
359 defaultline = noaction;
360 internalfunctions = find_export_symbols;
361 externalfunctions = find_export_symbols;
362 symbolsonly = find_export_symbols;
363 singlefunctions = noaction2;
364 parse_file(infile);
366 /* Rewind to start from beginning of file again */
367 fseek(infile, 0, SEEK_SET);
368 defaultline = printline;
369 internalfunctions = intfunc;
370 externalfunctions = extfunc;
371 symbolsonly = printline;
372 singlefunctions = singfunc;
374 parse_file(infile);
375 }
376 else if (strcmp("depend", argv[1]) == 0)
377 {
378 /* Create first part of dependency chain
379 * file.tmpl */
380 printf("%s\t", argv[2]);
381 defaultline = noaction;
382 internalfunctions = adddep;
383 externalfunctions = adddep;
384 symbolsonly = adddep;
385 singlefunctions = adddep2;
386 parse_file(infile);
387 printf("\n");
388 }
389 else
390 {
391 fprintf(stderr, "Unknown option: %s\n", argv[1]);
392 exit(1);
393 }
394 fclose(infile);
395 fflush(stdout);
396 return exitstatus;
397 }