lib/kasprintf.c: introduce kvasprintf_const
This adds kvasprintf_const which tries to use kstrdup_const if possible: If the format string contains no % characters, or if the format string is exactly "%s", we delegate to kstrdup_const. Otherwise, we fall back to kvasprintf. Just as for kstrdup_const, the main motivation is to save memory by reusing .rodata when possible. The return value should be freed by kfree_const, just like for kstrdup_const. There is deliberately no kasprintf_const: In the vast majority of cases, the format string argument is a literal, so one can determine statically whether one could instead use kstrdup_const directly (which would also require one to change all corresponding kfree calls to kfree_const). Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> Cc: Greg KH <greg@kroah.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
2cf12f821c
commit
0a9df786a6
|
@ -413,6 +413,8 @@ extern __printf(2, 3)
|
||||||
char *kasprintf(gfp_t gfp, const char *fmt, ...);
|
char *kasprintf(gfp_t gfp, const char *fmt, ...);
|
||||||
extern __printf(2, 0)
|
extern __printf(2, 0)
|
||||||
char *kvasprintf(gfp_t gfp, const char *fmt, va_list args);
|
char *kvasprintf(gfp_t gfp, const char *fmt, va_list args);
|
||||||
|
extern __printf(2, 0)
|
||||||
|
const char *kvasprintf_const(gfp_t gfp, const char *fmt, va_list args);
|
||||||
|
|
||||||
extern __scanf(2, 3)
|
extern __scanf(2, 3)
|
||||||
int sscanf(const char *, const char *, ...);
|
int sscanf(const char *, const char *, ...);
|
||||||
|
|
|
@ -31,6 +31,22 @@ char *kvasprintf(gfp_t gfp, const char *fmt, va_list ap)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(kvasprintf);
|
EXPORT_SYMBOL(kvasprintf);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If fmt contains no % (or is exactly %s), use kstrdup_const. If fmt
|
||||||
|
* (or the sole vararg) points to rodata, we will then save a memory
|
||||||
|
* allocation and string copy. In any case, the return value should be
|
||||||
|
* freed using kfree_const().
|
||||||
|
*/
|
||||||
|
const char *kvasprintf_const(gfp_t gfp, const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
if (!strchr(fmt, '%'))
|
||||||
|
return kstrdup_const(fmt, gfp);
|
||||||
|
if (!strcmp(fmt, "%s"))
|
||||||
|
return kstrdup_const(va_arg(ap, const char*), gfp);
|
||||||
|
return kvasprintf(gfp, fmt, ap);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(kvasprintf_const);
|
||||||
|
|
||||||
char *kasprintf(gfp_t gfp, const char *fmt, ...)
|
char *kasprintf(gfp_t gfp, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
Loading…
Reference in New Issue