[4/4] export: avoid code duplication in include/linux/export.h
diff mbox series

Message ID 20191010151443.7399-5-maennich@google.com
State New
Headers show
Series
  • export/modpost: avoid renaming __ksymtab entries for symbol namespaces
Related show

Commit Message

Matthias Maennich Oct. 10, 2019, 3:14 p.m. UTC
Now that the namespace value is not part of the __ksymtab entry name
anymore, we can simplify the implementation of EXPORT_SYMBOL*. By
allowing the empty string "" to represent 'no namespace', we can unify
the implementation and drop a lot redundant code.  That increases
readability and maintainability.

As Masahiro pointed out earlier,
"The drawback of this change is, it grows the code size. When the symbol
has no namespace, sym->namespace was previously NULL, but it is now am
empty string "". So, it increases 1 byte for every no namespace
EXPORT_SYMBOL. A typical kernel configuration has 10K exported symbols,
so it increases 10KB in rough estimation."

Suggested-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Signed-off-by: Matthias Maennich <maennich@google.com>
---
 include/linux/export.h | 92 +++++++++++++-----------------------------
 kernel/module.c        |  2 +-
 2 files changed, 29 insertions(+), 65 deletions(-)

Comments

Greg Kroah-Hartman Oct. 11, 2019, 3:31 p.m. UTC | #1
On Thu, Oct 10, 2019 at 04:14:43PM +0100, Matthias Maennich wrote:
> Now that the namespace value is not part of the __ksymtab entry name
> anymore, we can simplify the implementation of EXPORT_SYMBOL*. By
> allowing the empty string "" to represent 'no namespace', we can unify
> the implementation and drop a lot redundant code.  That increases
> readability and maintainability.
> 
> As Masahiro pointed out earlier,
> "The drawback of this change is, it grows the code size. When the symbol
> has no namespace, sym->namespace was previously NULL, but it is now am
> empty string "". So, it increases 1 byte for every no namespace
> EXPORT_SYMBOL. A typical kernel configuration has 10K exported symbols,
> so it increases 10KB in rough estimation."

10Kb of non-swapable memory isn't good.  But if you care about that, you
can get it back with the option to compile away any non-used symbols,
and that shouldn't be affected by this change, right?

That being said, the code is a lot cleaner, so I have no objection to
it.

Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Matthias Maennich Oct. 11, 2019, 3:43 p.m. UTC | #2
On Fri, Oct 11, 2019 at 05:31:27PM +0200, Greg Kroah-Hartman wrote:
>On Thu, Oct 10, 2019 at 04:14:43PM +0100, Matthias Maennich wrote:
>> Now that the namespace value is not part of the __ksymtab entry name
>> anymore, we can simplify the implementation of EXPORT_SYMBOL*. By
>> allowing the empty string "" to represent 'no namespace', we can unify
>> the implementation and drop a lot redundant code.  That increases
>> readability and maintainability.
>>
>> As Masahiro pointed out earlier,
>> "The drawback of this change is, it grows the code size. When the symbol
>> has no namespace, sym->namespace was previously NULL, but it is now am
>> empty string "". So, it increases 1 byte for every no namespace
>> EXPORT_SYMBOL. A typical kernel configuration has 10K exported symbols,
>> so it increases 10KB in rough estimation."
>
>10Kb of non-swapable memory isn't good.  But if you care about that, you
>can get it back with the option to compile away any non-used symbols,
>and that shouldn't be affected by this change, right?

Rasmus suggested to put the 'aMS' flags on the __ksymtab_strings section
to mitigate this:
https://lore.kernel.org/lkml/f2e28d6b-77c5-5fe2-0bc4-b24955de9954@rasmusvillemoes.dk/

I was not yet able to properly test this, so I did not include it in
this series. As I said in the cover letter, this 4th patch might be
optional for 5.4. So, we could defer it to a later time when we have
addressed that properly.

Cheers,
Matthias

>
>That being said, the code is a lot cleaner, so I have no objection to
>it.
>
>Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Masahiro Yamada Oct. 12, 2019, 4:25 a.m. UTC | #3
On Sat, Oct 12, 2019 at 12:43 AM Matthias Maennich <maennich@google.com> wrote:
>
> On Fri, Oct 11, 2019 at 05:31:27PM +0200, Greg Kroah-Hartman wrote:
> >On Thu, Oct 10, 2019 at 04:14:43PM +0100, Matthias Maennich wrote:
> >> Now that the namespace value is not part of the __ksymtab entry name
> >> anymore, we can simplify the implementation of EXPORT_SYMBOL*. By
> >> allowing the empty string "" to represent 'no namespace', we can unify
> >> the implementation and drop a lot redundant code.  That increases
> >> readability and maintainability.
> >>
> >> As Masahiro pointed out earlier,
> >> "The drawback of this change is, it grows the code size. When the symbol
> >> has no namespace, sym->namespace was previously NULL, but it is now am
> >> empty string "". So, it increases 1 byte for every no namespace
> >> EXPORT_SYMBOL. A typical kernel configuration has 10K exported symbols,
> >> so it increases 10KB in rough estimation."
> >
> >10Kb of non-swapable memory isn't good.  But if you care about that, you
> >can get it back with the option to compile away any non-used symbols,
> >and that shouldn't be affected by this change, right?
>
> Rasmus suggested to put the 'aMS' flags on the __ksymtab_strings section
> to mitigate this:
> https://lore.kernel.org/lkml/f2e28d6b-77c5-5fe2-0bc4-b24955de9954@rasmusvillemoes.dk/
>
> I was not yet able to properly test this, so I did not include it in
> this series. As I said in the cover letter, this 4th patch might be
> optional for 5.4. So, we could defer it to a later time when we have
> addressed that properly.


This looks the same as my patch, though.

Reviewed-by: Masahiro Yamada <yamada.masahiro@socionext.com>

Patch
diff mbox series

diff --git a/include/linux/export.h b/include/linux/export.h
index f24b86d7dd4d..201262793369 100644
--- a/include/linux/export.h
+++ b/include/linux/export.h
@@ -46,7 +46,7 @@  extern struct module __this_module;
  * absolute relocations that require runtime processing on relocatable
  * kernels.
  */
-#define __KSYMTAB_ENTRY_NS(sym, sec)					\
+#define __KSYMTAB_ENTRY(sym, sec)					\
 	__ADDRESSABLE(sym)						\
 	asm("	.section \"___ksymtab" sec "+" #sym "\", \"a\"	\n"	\
 	    "	.balign	4					\n"	\
@@ -56,34 +56,17 @@  extern struct module __this_module;
 	    "	.long	__kstrtabns_" #sym "- .			\n"	\
 	    "	.previous					\n")
 
-#define __KSYMTAB_ENTRY(sym, sec)					\
-	__ADDRESSABLE(sym)						\
-	asm("	.section \"___ksymtab" sec "+" #sym "\", \"a\"	\n"	\
-	    "	.balign 4					\n"	\
-	    "__ksymtab_" #sym ":				\n"	\
-	    "	.long	" #sym "- .				\n"	\
-	    "	.long	__kstrtab_" #sym "- .			\n"	\
-	    "	.long	0					\n"	\
-	    "	.previous					\n")
-
 struct kernel_symbol {
 	int value_offset;
 	int name_offset;
 	int namespace_offset;
 };
 #else
-#define __KSYMTAB_ENTRY_NS(sym, sec)					\
-	static const struct kernel_symbol __ksymtab_##sym		\
-	__attribute__((section("___ksymtab" sec "+" #sym), used))	\
-	__aligned(sizeof(void *))					\
-	= { (unsigned long)&sym, __kstrtab_##sym, __kstrtabns_##sym }
-
 #define __KSYMTAB_ENTRY(sym, sec)					\
 	static const struct kernel_symbol __ksymtab_##sym		\
-	asm("__ksymtab_" #sym)						\
 	__attribute__((section("___ksymtab" sec "+" #sym), used))	\
 	__aligned(sizeof(void *))					\
-	= { (unsigned long)&sym, __kstrtab_##sym, NULL }
+	= { (unsigned long)&sym, __kstrtab_##sym, __kstrtabns_##sym }
 
 struct kernel_symbol {
 	unsigned long value;
@@ -94,28 +77,20 @@  struct kernel_symbol {
 
 #ifdef __GENKSYMS__
 
-#define ___EXPORT_SYMBOL(sym,sec)	__GENKSYMS_EXPORT_SYMBOL(sym)
-#define ___EXPORT_SYMBOL_NS(sym,sec,ns)	__GENKSYMS_EXPORT_SYMBOL(sym)
+#define ___EXPORT_SYMBOL(sym, sec, ns)	__GENKSYMS_EXPORT_SYMBOL(sym)
 
 #else
 
-#define ___export_symbol_common(sym, sec)				\
+/* For every exported symbol, place a struct in the __ksymtab section */
+#define ___EXPORT_SYMBOL(sym, sec, ns)					\
 	extern typeof(sym) sym;						\
 	__CRC_SYMBOL(sym, sec);						\
 	static const char __kstrtab_##sym[]				\
 	__attribute__((section("__ksymtab_strings"), used, aligned(1)))	\
-	= #sym								\
-
-/* For every exported symbol, place a struct in the __ksymtab section */
-#define ___EXPORT_SYMBOL_NS(sym, sec, ns)				\
-	___export_symbol_common(sym, sec);				\
+	= #sym;								\
 	static const char __kstrtabns_##sym[]				\
 	__attribute__((section("__ksymtab_strings"), used, aligned(1)))	\
-	= #ns;								\
-	__KSYMTAB_ENTRY_NS(sym, sec)
-
-#define ___EXPORT_SYMBOL(sym, sec)					\
-	___export_symbol_common(sym, sec);				\
+	= ns;								\
 	__KSYMTAB_ENTRY(sym, sec)
 
 #endif
@@ -127,8 +102,7 @@  struct kernel_symbol {
  * be reused in other execution contexts such as the UEFI stub or the
  * decompressor.
  */
-#define __EXPORT_SYMBOL_NS(sym, sec, ns)
-#define __EXPORT_SYMBOL(sym, sec)
+#define __EXPORT_SYMBOL(sym, sec, ns)
 
 #elif defined(CONFIG_TRIM_UNUSED_KSYMS)
 
@@ -144,48 +118,38 @@  struct kernel_symbol {
 #define __ksym_marker(sym)	\
 	static int __ksym_marker_##sym[0] __section(".discard.ksym") __used
 
-#define __EXPORT_SYMBOL(sym, sec)				\
-	__ksym_marker(sym);					\
-	__cond_export_sym(sym, sec, __is_defined(__KSYM_##sym))
-#define __cond_export_sym(sym, sec, conf)			\
-	___cond_export_sym(sym, sec, conf)
-#define ___cond_export_sym(sym, sec, enabled)			\
-	__cond_export_sym_##enabled(sym, sec)
-#define __cond_export_sym_1(sym, sec) ___EXPORT_SYMBOL(sym, sec)
-#define __cond_export_sym_0(sym, sec) /* nothing */
-
-#define __EXPORT_SYMBOL_NS(sym, sec, ns)				\
+#define __EXPORT_SYMBOL(sym, sec, ns)					\
 	__ksym_marker(sym);						\
-	__cond_export_ns_sym(sym, sec, ns, __is_defined(__KSYM_##sym))
-#define __cond_export_ns_sym(sym, sec, ns, conf)			\
-	___cond_export_ns_sym(sym, sec, ns, conf)
-#define ___cond_export_ns_sym(sym, sec, ns, enabled)			\
-	__cond_export_ns_sym_##enabled(sym, sec, ns)
-#define __cond_export_ns_sym_1(sym, sec, ns) ___EXPORT_SYMBOL_NS(sym, sec, ns)
-#define __cond_export_ns_sym_0(sym, sec, ns) /* nothing */
+	__cond_export_sym(sym, sec, ns, __is_defined(__KSYM_##sym))
+#define __cond_export_sym(sym, sec, ns, conf)				\
+	___cond_export_sym(sym, sec, ns, conf)
+#define ___cond_export_sym(sym, sec, ns, enabled)			\
+	__cond_export_sym_##enabled(sym, sec, ns)
+#define __cond_export_sym_1(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns)
+#define __cond_export_sym_0(sym, sec, ns) /* nothing */
 
 #else
 
-#define __EXPORT_SYMBOL_NS(sym,sec,ns)	___EXPORT_SYMBOL_NS(sym,sec,ns)
-#define __EXPORT_SYMBOL(sym,sec)	___EXPORT_SYMBOL(sym,sec)
+#define __EXPORT_SYMBOL(sym, sec, ns)	___EXPORT_SYMBOL(sym, sec, ns)
 
 #endif /* CONFIG_MODULES */
 
 #ifdef DEFAULT_SYMBOL_NAMESPACE
-#undef __EXPORT_SYMBOL
-#define __EXPORT_SYMBOL(sym, sec)				\
-	__EXPORT_SYMBOL_NS(sym, sec, DEFAULT_SYMBOL_NAMESPACE)
+#include <linux/stringify.h>
+#define _EXPORT_SYMBOL(sym, sec)	__EXPORT_SYMBOL(sym, sec, __stringify(DEFAULT_SYMBOL_NAMESPACE))
+#else
+#define _EXPORT_SYMBOL(sym, sec)	__EXPORT_SYMBOL(sym, sec, "")
 #endif
 
-#define EXPORT_SYMBOL(sym)		__EXPORT_SYMBOL(sym, "")
-#define EXPORT_SYMBOL_GPL(sym)		__EXPORT_SYMBOL(sym, "_gpl")
-#define EXPORT_SYMBOL_GPL_FUTURE(sym)	__EXPORT_SYMBOL(sym, "_gpl_future")
-#define EXPORT_SYMBOL_NS(sym, ns)	__EXPORT_SYMBOL_NS(sym, "", ns)
-#define EXPORT_SYMBOL_NS_GPL(sym, ns)	__EXPORT_SYMBOL_NS(sym, "_gpl", ns)
+#define EXPORT_SYMBOL(sym)		_EXPORT_SYMBOL(sym, "")
+#define EXPORT_SYMBOL_GPL(sym)		_EXPORT_SYMBOL(sym, "_gpl")
+#define EXPORT_SYMBOL_GPL_FUTURE(sym)	_EXPORT_SYMBOL(sym, "_gpl_future")
+#define EXPORT_SYMBOL_NS(sym, ns)	__EXPORT_SYMBOL(sym, "", #ns)
+#define EXPORT_SYMBOL_NS_GPL(sym, ns)	__EXPORT_SYMBOL(sym, "_gpl", #ns)
 
 #ifdef CONFIG_UNUSED_SYMBOLS
-#define EXPORT_UNUSED_SYMBOL(sym)	__EXPORT_SYMBOL(sym, "_unused")
-#define EXPORT_UNUSED_SYMBOL_GPL(sym)	__EXPORT_SYMBOL(sym, "_unused_gpl")
+#define EXPORT_UNUSED_SYMBOL(sym)	_EXPORT_SYMBOL(sym, "_unused")
+#define EXPORT_UNUSED_SYMBOL_GPL(sym)	_EXPORT_SYMBOL(sym, "_unused_gpl")
 #else
 #define EXPORT_UNUSED_SYMBOL(sym)
 #define EXPORT_UNUSED_SYMBOL_GPL(sym)
diff --git a/kernel/module.c b/kernel/module.c
index ff2d7359a418..26c13173da3d 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1400,7 +1400,7 @@  static int verify_namespace_is_imported(const struct load_info *info,
 	char *imported_namespace;
 
 	namespace = kernel_symbol_namespace(sym);
-	if (namespace) {
+	if (namespace && namespace[0]) {
 		imported_namespace = get_modinfo(info, "import_ns");
 		while (imported_namespace) {
 			if (strcmp(namespace, imported_namespace) == 0)