struct va_format is used to facilitate implementation of variadic functions. Most of variadic users do not parse arguments one by one, they just forward them to some helper via va_format pointer. Introduced helpers simplifies it more. Signed-off-by: Andrzej Hajda --- include/linux/printk.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/include/linux/printk.h b/include/linux/printk.h index 45c663124c9bd3b294031d839f1253f410313faa..6fd817ce29a66b33a804b660c2b770efa110ee7e 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -87,6 +87,36 @@ struct va_format { va_list *va; }; +/* Special macro used only by callers of va_format_call to position va_format argument */ +#define va_format_arg (&vaf) + +/** + * va_format_call() - forward variable arguments to va_format aware function + * @_fmt: format used by @_func function + * @_func: function which should be called + * @_args: arguments passed to @_func. Exactly one of them must be va_format_arg, + * to indicate position of *va_format type arg in arguments of @_func. + * + * Many variadic functions just forwards their variadic arguments to some helper + * function via va_format pointer. It involves few common steps encapsulated in + * this macro. The macro is accompanied by va_format_arg macro, described above. + * Sample implementation of common helper: + * void dev_err(struct device *dev, const char* fmt, ...) + * { + * va_format_call(fmt, pr_err, "%s %s: %pV", dev_driver_string(dev), + * dev_name(dev), va_format_arg); + * } + */ +#define va_format_call(_fmt, _func, _args...) \ +({ \ + va_list ap; \ + struct va_format vaf = { .fmt = _fmt, .va = &ap }; \ + \ + va_start(ap, _fmt); \ + _func(_args); \ + va_end(ap); \ +}) + /* * FW_BUG * Add this to a message where you are sure the firmware is buggy or behaves -- 2.43.0 It simplifies the code and makes it more clear. Signed-off-by: Andrzej Hajda --- drivers/base/core.c | 32 ++++++-------------------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index f69dc9c8595455d85bf7eda5d4abce1ed7cb5166..513e5ef8a6dabaec0aee0778c1338a9d72e66892 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -4943,35 +4943,15 @@ static void __dev_printk(const char *level, const struct device *dev, void _dev_printk(const char *level, const struct device *dev, const char *fmt, ...) { - struct va_format vaf; - va_list args; - - va_start(args, fmt); - - vaf.fmt = fmt; - vaf.va = &args; - - __dev_printk(level, dev, &vaf); - - va_end(args); + va_format_call(fmt, __dev_printk, level, dev, va_format_arg); } EXPORT_SYMBOL(_dev_printk); -#define define_dev_printk_level(func, kern_level) \ -void func(const struct device *dev, const char *fmt, ...) \ -{ \ - struct va_format vaf; \ - va_list args; \ - \ - va_start(args, fmt); \ - \ - vaf.fmt = fmt; \ - vaf.va = &args; \ - \ - __dev_printk(kern_level, dev, &vaf); \ - \ - va_end(args); \ -} \ +#define define_dev_printk_level(func, kern_level) \ +void func(const struct device *dev, const char *fmt, ...) \ +{ \ + va_format_call(fmt, __dev_printk, kern_level, dev, va_format_arg); \ +} \ EXPORT_SYMBOL(func); define_dev_printk_level(_dev_emerg, KERN_EMERG); -- 2.43.0 It simplifies the code and makes it more clear. Signed-off-by: Andrzej Hajda --- mm/page_alloc.c | 14 ++++---------- mm/slub.c | 10 +--------- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index ed82ee55e66afffafcf6360b13da410119f2898d..cd0b17ea4de0a3262fae117fac7f427a7396978f 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3940,22 +3940,16 @@ static void warn_alloc_show_mem(gfp_t gfp_mask, nodemask_t *nodemask) void warn_alloc(gfp_t gfp_mask, nodemask_t *nodemask, const char *fmt, ...) { - struct va_format vaf; - va_list args; static DEFINE_RATELIMIT_STATE(nopage_rs, 10*HZ, 1); if ((gfp_mask & __GFP_NOWARN) || !__ratelimit(&nopage_rs) || ((gfp_mask & __GFP_DMA) && !has_managed_dma())) return; - - va_start(args, fmt); - vaf.fmt = fmt; - vaf.va = &args; - pr_warn("%s: %pV, mode:%#x(%pGg), nodemask=%*pbl", - current->comm, &vaf, gfp_mask, &gfp_mask, - nodemask_pr_args(nodemask)); - va_end(args); + va_format_call(fmt, pr_warn, + "%s: %pV, mode:%#x(%pGg), nodemask=%*pbl", + current->comm, va_format_arg, gfp_mask, &gfp_mask, + nodemask_pr_args(nodemask)); cpuset_print_current_mems_allowed(); pr_cont("\n"); diff --git a/mm/slub.c b/mm/slub.c index 1a5fc34290421ea32e6f5bba8acc87b53a9774b5..786c5a4195d44d5c40b3c9009ff52a3b836bfe23 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1161,17 +1161,9 @@ static void slab_bug(struct kmem_cache *s, const char *fmt, ...) __printf(2, 3) static void slab_fix(struct kmem_cache *s, const char *fmt, ...) { - struct va_format vaf; - va_list args; - if (slab_add_kunit_errors()) return; - - va_start(args, fmt); - vaf.fmt = fmt; - vaf.va = &args; - pr_err("FIX %s: %pV\n", s->name, &vaf); - va_end(args); + va_format_call(fmt, pr_err, "FIX %s: %pV\n", s->name, va_format_arg); } static void print_trailer(struct kmem_cache *s, struct slab *slab, u8 *p) -- 2.43.0