From e6de04b73cfaa1b17eee531d472cbbd37c247502 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Thu, 24 Jun 2010 09:41:59 -0700 Subject: [PATCH] Add kmem_vasprintf function We might as well have both asprintf() variants. This allows us to safely pass a va_list through several levels of the stack using va_copy() instead of va_start(). --- include/sys/kmem.h | 1 + module/spl/spl-kmem.c | 26 +++++++++++++++++++++----- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/include/sys/kmem.h b/include/sys/kmem.h index a5ee4e0df2..9688b116df 100644 --- a/include/sys/kmem.h +++ b/include/sys/kmem.h @@ -248,6 +248,7 @@ enum { #define KMC_DEFAULT_SEEKS 1 extern int kmem_debugging(void); +extern char *kmem_vasprintf(const char *fmt, va_list ap); extern char *kmem_asprintf(const char *fmt, ...); #define strfree(str) kfree(str) #define strdup(str) kstrdup(str, GFP_KERNEL) diff --git a/module/spl/spl-kmem.c b/module/spl/spl-kmem.c index 4620eb9bf9..a348021d88 100644 --- a/module/spl/spl-kmem.c +++ b/module/spl/spl-kmem.c @@ -239,16 +239,32 @@ EXPORT_SYMBOL(kvasprintf); #endif /* HAVE_KVASPRINTF */ char * -kmem_asprintf(const char *fmt, ...) +kmem_vasprintf(const char *fmt, va_list ap) { - va_list args; + va_list aq; char *ptr; - va_start(args, fmt); + va_copy(aq, ap); do { - ptr = kvasprintf(GFP_KERNEL, fmt, args); + ptr = kvasprintf(GFP_KERNEL, fmt, aq); } while (ptr == NULL); - va_end(args); + va_end(aq); + + return ptr; +} +EXPORT_SYMBOL(kmem_vasprintf); + +char * +kmem_asprintf(const char *fmt, ...) +{ + va_list ap; + char *ptr; + + va_start(ap, fmt); + do { + ptr = kvasprintf(GFP_KERNEL, fmt, ap); + } while (ptr == NULL); + va_end(ap); return ptr; }