ia64/linux-2.6.18-xen.hg

view lib/vsprintf.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 * linux/lib/vsprintf.c
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 */
7 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
8 /*
9 * Wirzenius wrote this portably, Torvalds fucked it up :-)
10 */
12 /*
13 * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
14 * - changed to provide snprintf and vsnprintf functions
15 * So Feb 1 16:51:32 CET 2004 Juergen Quade <quade@hsnr.de>
16 * - scnprintf and vscnprintf
17 */
19 #include <stdarg.h>
20 #include <linux/module.h>
21 #include <linux/types.h>
22 #include <linux/string.h>
23 #include <linux/ctype.h>
24 #include <linux/kernel.h>
26 #include <asm/page.h> /* for PAGE_SIZE */
27 #include <asm/div64.h>
29 /**
30 * simple_strtoul - convert a string to an unsigned long
31 * @cp: The start of the string
32 * @endp: A pointer to the end of the parsed string will be placed here
33 * @base: The number base to use
34 */
35 unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
36 {
37 unsigned long result = 0,value;
39 if (!base) {
40 base = 10;
41 if (*cp == '0') {
42 base = 8;
43 cp++;
44 if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
45 cp++;
46 base = 16;
47 }
48 }
49 } else if (base == 16) {
50 if (cp[0] == '0' && toupper(cp[1]) == 'X')
51 cp += 2;
52 }
53 while (isxdigit(*cp) &&
54 (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
55 result = result*base + value;
56 cp++;
57 }
58 if (endp)
59 *endp = (char *)cp;
60 return result;
61 }
63 EXPORT_SYMBOL(simple_strtoul);
65 /**
66 * simple_strtol - convert a string to a signed long
67 * @cp: The start of the string
68 * @endp: A pointer to the end of the parsed string will be placed here
69 * @base: The number base to use
70 */
71 long simple_strtol(const char *cp,char **endp,unsigned int base)
72 {
73 if(*cp=='-')
74 return -simple_strtoul(cp+1,endp,base);
75 return simple_strtoul(cp,endp,base);
76 }
78 EXPORT_SYMBOL(simple_strtol);
80 /**
81 * simple_strtoull - convert a string to an unsigned long long
82 * @cp: The start of the string
83 * @endp: A pointer to the end of the parsed string will be placed here
84 * @base: The number base to use
85 */
86 unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
87 {
88 unsigned long long result = 0,value;
90 if (!base) {
91 base = 10;
92 if (*cp == '0') {
93 base = 8;
94 cp++;
95 if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
96 cp++;
97 base = 16;
98 }
99 }
100 } else if (base == 16) {
101 if (cp[0] == '0' && toupper(cp[1]) == 'X')
102 cp += 2;
103 }
104 while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
105 ? toupper(*cp) : *cp)-'A'+10) < base) {
106 result = result*base + value;
107 cp++;
108 }
109 if (endp)
110 *endp = (char *)cp;
111 return result;
112 }
114 EXPORT_SYMBOL(simple_strtoull);
116 /**
117 * simple_strtoll - convert a string to a signed long long
118 * @cp: The start of the string
119 * @endp: A pointer to the end of the parsed string will be placed here
120 * @base: The number base to use
121 */
122 long long simple_strtoll(const char *cp,char **endp,unsigned int base)
123 {
124 if(*cp=='-')
125 return -simple_strtoull(cp+1,endp,base);
126 return simple_strtoull(cp,endp,base);
127 }
129 static int skip_atoi(const char **s)
130 {
131 int i=0;
133 while (isdigit(**s))
134 i = i*10 + *((*s)++) - '0';
135 return i;
136 }
138 #define ZEROPAD 1 /* pad with zero */
139 #define SIGN 2 /* unsigned/signed long */
140 #define PLUS 4 /* show plus */
141 #define SPACE 8 /* space if plus */
142 #define LEFT 16 /* left justified */
143 #define SPECIAL 32 /* 0x */
144 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
146 static char * number(char * buf, char * end, unsigned long long num, int base, int size, int precision, int type)
147 {
148 char c,sign,tmp[66];
149 const char *digits;
150 static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
151 static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
152 int i;
154 digits = (type & LARGE) ? large_digits : small_digits;
155 if (type & LEFT)
156 type &= ~ZEROPAD;
157 if (base < 2 || base > 36)
158 return NULL;
159 c = (type & ZEROPAD) ? '0' : ' ';
160 sign = 0;
161 if (type & SIGN) {
162 if ((signed long long) num < 0) {
163 sign = '-';
164 num = - (signed long long) num;
165 size--;
166 } else if (type & PLUS) {
167 sign = '+';
168 size--;
169 } else if (type & SPACE) {
170 sign = ' ';
171 size--;
172 }
173 }
174 if (type & SPECIAL) {
175 if (base == 16)
176 size -= 2;
177 else if (base == 8)
178 size--;
179 }
180 i = 0;
181 if (num == 0)
182 tmp[i++]='0';
183 else while (num != 0)
184 tmp[i++] = digits[do_div(num,base)];
185 if (i > precision)
186 precision = i;
187 size -= precision;
188 if (!(type&(ZEROPAD+LEFT))) {
189 while(size-->0) {
190 if (buf < end)
191 *buf = ' ';
192 ++buf;
193 }
194 }
195 if (sign) {
196 if (buf < end)
197 *buf = sign;
198 ++buf;
199 }
200 if (type & SPECIAL) {
201 if (base==8) {
202 if (buf < end)
203 *buf = '0';
204 ++buf;
205 } else if (base==16) {
206 if (buf < end)
207 *buf = '0';
208 ++buf;
209 if (buf < end)
210 *buf = digits[33];
211 ++buf;
212 }
213 }
214 if (!(type & LEFT)) {
215 while (size-- > 0) {
216 if (buf < end)
217 *buf = c;
218 ++buf;
219 }
220 }
221 while (i < precision--) {
222 if (buf < end)
223 *buf = '0';
224 ++buf;
225 }
226 while (i-- > 0) {
227 if (buf < end)
228 *buf = tmp[i];
229 ++buf;
230 }
231 while (size-- > 0) {
232 if (buf < end)
233 *buf = ' ';
234 ++buf;
235 }
236 return buf;
237 }
239 /**
240 * vsnprintf - Format a string and place it in a buffer
241 * @buf: The buffer to place the result into
242 * @size: The size of the buffer, including the trailing null space
243 * @fmt: The format string to use
244 * @args: Arguments for the format string
245 *
246 * The return value is the number of characters which would
247 * be generated for the given input, excluding the trailing
248 * '\0', as per ISO C99. If you want to have the exact
249 * number of characters written into @buf as return value
250 * (not including the trailing '\0'), use vscnprintf. If the
251 * return is greater than or equal to @size, the resulting
252 * string is truncated.
253 *
254 * Call this function if you are already dealing with a va_list.
255 * You probably want snprintf instead.
256 */
257 int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
258 {
259 int len;
260 unsigned long long num;
261 int i, base;
262 char *str, *end, c;
263 const char *s;
265 int flags; /* flags to number() */
267 int field_width; /* width of output field */
268 int precision; /* min. # of digits for integers; max
269 number of chars for from string */
270 int qualifier; /* 'h', 'l', or 'L' for integer fields */
271 /* 'z' support added 23/7/1999 S.H. */
272 /* 'z' changed to 'Z' --davidm 1/25/99 */
273 /* 't' added for ptrdiff_t */
275 /* Reject out-of-range values early. Large positive sizes are
276 used for unknown buffer sizes. */
277 if (unlikely((int) size < 0)) {
278 /* There can be only one.. */
279 static int warn = 1;
280 WARN_ON(warn);
281 warn = 0;
282 return 0;
283 }
285 str = buf;
286 end = buf + size;
288 /* Make sure end is always >= buf */
289 if (end < buf) {
290 end = ((void *)-1);
291 size = end - buf;
292 }
294 for (; *fmt ; ++fmt) {
295 if (*fmt != '%') {
296 if (str < end)
297 *str = *fmt;
298 ++str;
299 continue;
300 }
302 /* process flags */
303 flags = 0;
304 repeat:
305 ++fmt; /* this also skips first '%' */
306 switch (*fmt) {
307 case '-': flags |= LEFT; goto repeat;
308 case '+': flags |= PLUS; goto repeat;
309 case ' ': flags |= SPACE; goto repeat;
310 case '#': flags |= SPECIAL; goto repeat;
311 case '0': flags |= ZEROPAD; goto repeat;
312 }
314 /* get field width */
315 field_width = -1;
316 if (isdigit(*fmt))
317 field_width = skip_atoi(&fmt);
318 else if (*fmt == '*') {
319 ++fmt;
320 /* it's the next argument */
321 field_width = va_arg(args, int);
322 if (field_width < 0) {
323 field_width = -field_width;
324 flags |= LEFT;
325 }
326 }
328 /* get the precision */
329 precision = -1;
330 if (*fmt == '.') {
331 ++fmt;
332 if (isdigit(*fmt))
333 precision = skip_atoi(&fmt);
334 else if (*fmt == '*') {
335 ++fmt;
336 /* it's the next argument */
337 precision = va_arg(args, int);
338 }
339 if (precision < 0)
340 precision = 0;
341 }
343 /* get the conversion qualifier */
344 qualifier = -1;
345 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
346 *fmt =='Z' || *fmt == 'z' || *fmt == 't') {
347 qualifier = *fmt;
348 ++fmt;
349 if (qualifier == 'l' && *fmt == 'l') {
350 qualifier = 'L';
351 ++fmt;
352 }
353 }
355 /* default base */
356 base = 10;
358 switch (*fmt) {
359 case 'c':
360 if (!(flags & LEFT)) {
361 while (--field_width > 0) {
362 if (str < end)
363 *str = ' ';
364 ++str;
365 }
366 }
367 c = (unsigned char) va_arg(args, int);
368 if (str < end)
369 *str = c;
370 ++str;
371 while (--field_width > 0) {
372 if (str < end)
373 *str = ' ';
374 ++str;
375 }
376 continue;
378 case 's':
379 s = va_arg(args, char *);
380 if ((unsigned long)s < PAGE_SIZE)
381 s = "<NULL>";
383 len = strnlen(s, precision);
385 if (!(flags & LEFT)) {
386 while (len < field_width--) {
387 if (str < end)
388 *str = ' ';
389 ++str;
390 }
391 }
392 for (i = 0; i < len; ++i) {
393 if (str < end)
394 *str = *s;
395 ++str; ++s;
396 }
397 while (len < field_width--) {
398 if (str < end)
399 *str = ' ';
400 ++str;
401 }
402 continue;
404 case 'p':
405 if (field_width == -1) {
406 field_width = 2*sizeof(void *);
407 flags |= ZEROPAD;
408 }
409 str = number(str, end,
410 (unsigned long) va_arg(args, void *),
411 16, field_width, precision, flags);
412 continue;
415 case 'n':
416 /* FIXME:
417 * What does C99 say about the overflow case here? */
418 if (qualifier == 'l') {
419 long * ip = va_arg(args, long *);
420 *ip = (str - buf);
421 } else if (qualifier == 'Z' || qualifier == 'z') {
422 size_t * ip = va_arg(args, size_t *);
423 *ip = (str - buf);
424 } else {
425 int * ip = va_arg(args, int *);
426 *ip = (str - buf);
427 }
428 continue;
430 case '%':
431 if (str < end)
432 *str = '%';
433 ++str;
434 continue;
436 /* integer number formats - set up the flags and "break" */
437 case 'o':
438 base = 8;
439 break;
441 case 'X':
442 flags |= LARGE;
443 case 'x':
444 base = 16;
445 break;
447 case 'd':
448 case 'i':
449 flags |= SIGN;
450 case 'u':
451 break;
453 default:
454 if (str < end)
455 *str = '%';
456 ++str;
457 if (*fmt) {
458 if (str < end)
459 *str = *fmt;
460 ++str;
461 } else {
462 --fmt;
463 }
464 continue;
465 }
466 if (qualifier == 'L')
467 num = va_arg(args, long long);
468 else if (qualifier == 'l') {
469 num = va_arg(args, unsigned long);
470 if (flags & SIGN)
471 num = (signed long) num;
472 } else if (qualifier == 'Z' || qualifier == 'z') {
473 num = va_arg(args, size_t);
474 } else if (qualifier == 't') {
475 num = va_arg(args, ptrdiff_t);
476 } else if (qualifier == 'h') {
477 num = (unsigned short) va_arg(args, int);
478 if (flags & SIGN)
479 num = (signed short) num;
480 } else {
481 num = va_arg(args, unsigned int);
482 if (flags & SIGN)
483 num = (signed int) num;
484 }
485 str = number(str, end, num, base,
486 field_width, precision, flags);
487 }
488 if (size > 0) {
489 if (str < end)
490 *str = '\0';
491 else
492 end[-1] = '\0';
493 }
494 /* the trailing null byte doesn't count towards the total */
495 return str-buf;
496 }
498 EXPORT_SYMBOL(vsnprintf);
500 /**
501 * vscnprintf - Format a string and place it in a buffer
502 * @buf: The buffer to place the result into
503 * @size: The size of the buffer, including the trailing null space
504 * @fmt: The format string to use
505 * @args: Arguments for the format string
506 *
507 * The return value is the number of characters which have been written into
508 * the @buf not including the trailing '\0'. If @size is <= 0 the function
509 * returns 0.
510 *
511 * Call this function if you are already dealing with a va_list.
512 * You probably want scnprintf instead.
513 */
514 int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
515 {
516 int i;
518 i=vsnprintf(buf,size,fmt,args);
519 return (i >= size) ? (size - 1) : i;
520 }
522 EXPORT_SYMBOL(vscnprintf);
524 /**
525 * snprintf - Format a string and place it in a buffer
526 * @buf: The buffer to place the result into
527 * @size: The size of the buffer, including the trailing null space
528 * @fmt: The format string to use
529 * @...: Arguments for the format string
530 *
531 * The return value is the number of characters which would be
532 * generated for the given input, excluding the trailing null,
533 * as per ISO C99. If the return is greater than or equal to
534 * @size, the resulting string is truncated.
535 */
536 int snprintf(char * buf, size_t size, const char *fmt, ...)
537 {
538 va_list args;
539 int i;
541 va_start(args, fmt);
542 i=vsnprintf(buf,size,fmt,args);
543 va_end(args);
544 return i;
545 }
547 EXPORT_SYMBOL(snprintf);
549 /**
550 * scnprintf - Format a string and place it in a buffer
551 * @buf: The buffer to place the result into
552 * @size: The size of the buffer, including the trailing null space
553 * @fmt: The format string to use
554 * @...: Arguments for the format string
555 *
556 * The return value is the number of characters written into @buf not including
557 * the trailing '\0'. If @size is <= 0 the function returns 0. If the return is
558 * greater than or equal to @size, the resulting string is truncated.
559 */
561 int scnprintf(char * buf, size_t size, const char *fmt, ...)
562 {
563 va_list args;
564 int i;
566 va_start(args, fmt);
567 i = vsnprintf(buf, size, fmt, args);
568 va_end(args);
569 return (i >= size) ? (size - 1) : i;
570 }
571 EXPORT_SYMBOL(scnprintf);
573 /**
574 * vsprintf - Format a string and place it in a buffer
575 * @buf: The buffer to place the result into
576 * @fmt: The format string to use
577 * @args: Arguments for the format string
578 *
579 * The function returns the number of characters written
580 * into @buf. Use vsnprintf or vscnprintf in order to avoid
581 * buffer overflows.
582 *
583 * Call this function if you are already dealing with a va_list.
584 * You probably want sprintf instead.
585 */
586 int vsprintf(char *buf, const char *fmt, va_list args)
587 {
588 return vsnprintf(buf, INT_MAX, fmt, args);
589 }
591 EXPORT_SYMBOL(vsprintf);
593 /**
594 * sprintf - Format a string and place it in a buffer
595 * @buf: The buffer to place the result into
596 * @fmt: The format string to use
597 * @...: Arguments for the format string
598 *
599 * The function returns the number of characters written
600 * into @buf. Use snprintf or scnprintf in order to avoid
601 * buffer overflows.
602 */
603 int sprintf(char * buf, const char *fmt, ...)
604 {
605 va_list args;
606 int i;
608 va_start(args, fmt);
609 i=vsnprintf(buf, INT_MAX, fmt, args);
610 va_end(args);
611 return i;
612 }
614 EXPORT_SYMBOL(sprintf);
616 /**
617 * vsscanf - Unformat a buffer into a list of arguments
618 * @buf: input buffer
619 * @fmt: format of buffer
620 * @args: arguments
621 */
622 int vsscanf(const char * buf, const char * fmt, va_list args)
623 {
624 const char *str = buf;
625 char *next;
626 char digit;
627 int num = 0;
628 int qualifier;
629 int base;
630 int field_width;
631 int is_sign = 0;
633 while(*fmt && *str) {
634 /* skip any white space in format */
635 /* white space in format matchs any amount of
636 * white space, including none, in the input.
637 */
638 if (isspace(*fmt)) {
639 while (isspace(*fmt))
640 ++fmt;
641 while (isspace(*str))
642 ++str;
643 }
645 /* anything that is not a conversion must match exactly */
646 if (*fmt != '%' && *fmt) {
647 if (*fmt++ != *str++)
648 break;
649 continue;
650 }
652 if (!*fmt)
653 break;
654 ++fmt;
656 /* skip this conversion.
657 * advance both strings to next white space
658 */
659 if (*fmt == '*') {
660 while (!isspace(*fmt) && *fmt)
661 fmt++;
662 while (!isspace(*str) && *str)
663 str++;
664 continue;
665 }
667 /* get field width */
668 field_width = -1;
669 if (isdigit(*fmt))
670 field_width = skip_atoi(&fmt);
672 /* get conversion qualifier */
673 qualifier = -1;
674 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
675 *fmt == 'Z' || *fmt == 'z') {
676 qualifier = *fmt++;
677 if (unlikely(qualifier == *fmt)) {
678 if (qualifier == 'h') {
679 qualifier = 'H';
680 fmt++;
681 } else if (qualifier == 'l') {
682 qualifier = 'L';
683 fmt++;
684 }
685 }
686 }
687 base = 10;
688 is_sign = 0;
690 if (!*fmt || !*str)
691 break;
693 switch(*fmt++) {
694 case 'c':
695 {
696 char *s = (char *) va_arg(args,char*);
697 if (field_width == -1)
698 field_width = 1;
699 do {
700 *s++ = *str++;
701 } while (--field_width > 0 && *str);
702 num++;
703 }
704 continue;
705 case 's':
706 {
707 char *s = (char *) va_arg(args, char *);
708 if(field_width == -1)
709 field_width = INT_MAX;
710 /* first, skip leading white space in buffer */
711 while (isspace(*str))
712 str++;
714 /* now copy until next white space */
715 while (*str && !isspace(*str) && field_width--) {
716 *s++ = *str++;
717 }
718 *s = '\0';
719 num++;
720 }
721 continue;
722 case 'n':
723 /* return number of characters read so far */
724 {
725 int *i = (int *)va_arg(args,int*);
726 *i = str - buf;
727 }
728 continue;
729 case 'o':
730 base = 8;
731 break;
732 case 'x':
733 case 'X':
734 base = 16;
735 break;
736 case 'i':
737 base = 0;
738 case 'd':
739 is_sign = 1;
740 case 'u':
741 break;
742 case '%':
743 /* looking for '%' in str */
744 if (*str++ != '%')
745 return num;
746 continue;
747 default:
748 /* invalid format; stop here */
749 return num;
750 }
752 /* have some sort of integer conversion.
753 * first, skip white space in buffer.
754 */
755 while (isspace(*str))
756 str++;
758 digit = *str;
759 if (is_sign && digit == '-')
760 digit = *(str + 1);
762 if (!digit
763 || (base == 16 && !isxdigit(digit))
764 || (base == 10 && !isdigit(digit))
765 || (base == 8 && (!isdigit(digit) || digit > '7'))
766 || (base == 0 && !isdigit(digit)))
767 break;
769 switch(qualifier) {
770 case 'H': /* that's 'hh' in format */
771 if (is_sign) {
772 signed char *s = (signed char *) va_arg(args,signed char *);
773 *s = (signed char) simple_strtol(str,&next,base);
774 } else {
775 unsigned char *s = (unsigned char *) va_arg(args, unsigned char *);
776 *s = (unsigned char) simple_strtoul(str, &next, base);
777 }
778 break;
779 case 'h':
780 if (is_sign) {
781 short *s = (short *) va_arg(args,short *);
782 *s = (short) simple_strtol(str,&next,base);
783 } else {
784 unsigned short *s = (unsigned short *) va_arg(args, unsigned short *);
785 *s = (unsigned short) simple_strtoul(str, &next, base);
786 }
787 break;
788 case 'l':
789 if (is_sign) {
790 long *l = (long *) va_arg(args,long *);
791 *l = simple_strtol(str,&next,base);
792 } else {
793 unsigned long *l = (unsigned long*) va_arg(args,unsigned long*);
794 *l = simple_strtoul(str,&next,base);
795 }
796 break;
797 case 'L':
798 if (is_sign) {
799 long long *l = (long long*) va_arg(args,long long *);
800 *l = simple_strtoll(str,&next,base);
801 } else {
802 unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*);
803 *l = simple_strtoull(str,&next,base);
804 }
805 break;
806 case 'Z':
807 case 'z':
808 {
809 size_t *s = (size_t*) va_arg(args,size_t*);
810 *s = (size_t) simple_strtoul(str,&next,base);
811 }
812 break;
813 default:
814 if (is_sign) {
815 int *i = (int *) va_arg(args, int*);
816 *i = (int) simple_strtol(str,&next,base);
817 } else {
818 unsigned int *i = (unsigned int*) va_arg(args, unsigned int*);
819 *i = (unsigned int) simple_strtoul(str,&next,base);
820 }
821 break;
822 }
823 num++;
825 if (!next)
826 break;
827 str = next;
828 }
829 return num;
830 }
832 EXPORT_SYMBOL(vsscanf);
834 /**
835 * sscanf - Unformat a buffer into a list of arguments
836 * @buf: input buffer
837 * @fmt: formatting of buffer
838 * @...: resulting arguments
839 */
840 int sscanf(const char * buf, const char * fmt, ...)
841 {
842 va_list args;
843 int i;
845 va_start(args,fmt);
846 i = vsscanf(buf,fmt,args);
847 va_end(args);
848 return i;
849 }
851 EXPORT_SYMBOL(sscanf);
854 /* Simplified asprintf. */
855 char *kasprintf(gfp_t gfp, const char *fmt, ...)
856 {
857 va_list ap;
858 unsigned int len;
859 char *p;
861 va_start(ap, fmt);
862 len = vsnprintf(NULL, 0, fmt, ap);
863 va_end(ap);
865 p = kmalloc(len+1, gfp);
866 if (!p)
867 return NULL;
868 va_start(ap, fmt);
869 vsnprintf(p, len+1, fmt, ap);
870 va_end(ap);
871 return p;
872 }
874 EXPORT_SYMBOL(kasprintf);