include/linux/memory.h: implement register_hotmemory_notifier()
authorAndrew Morton <akpm@linux-foundation.org>
Mon, 29 Apr 2013 22:08:04 +0000 (15:08 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 29 Apr 2013 22:54:36 +0000 (15:54 -0700)
When CONFIG_MEMORY_HOTPLUG=n, we don't want the memory-hotplug notifier
handlers to be included in the .o files, for space reasons.

The existing hotplug_memory_notifier() tries to handle this but testing
with gcc-4.4.4 shows that it doesn't work - the hotplug functions are
still present in the .o files.

So implement a new register_hotmemory_notifier() which is a copy of
register_hotcpu_notifier(), and which actually works as desired.
hotplug_memory_notifier() and register_memory_notifier() callsites
should be converted to use this new register_hotmemory_notifier().

While we're there, let's repair the existing hotplug_memory_notifier():
it simply stomps on the register_memory_notifier() return value, so
well-behaved code cannot check for errors.  Apparently non of the
existing callers were well-behaved :(

Cc: Andrew Shewmaker <agshew@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
include/linux/memory.h
include/linux/notifier.h

index 45e93b4688785a9502c870758220e57498723a94..0ff6598ee62f4a0e0ebaeb5e6f4fdeae4360facd 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/node.h>
 #include <linux/compiler.h>
 #include <linux/mutex.h>
+#include <linux/notifier.h>
 
 #define MIN_MEMORY_BLOCK_SIZE     (1UL << SECTION_SIZE_BITS)
 
@@ -127,13 +128,18 @@ enum mem_add_context { BOOT, HOTPLUG };
 #endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-#define hotplug_memory_notifier(fn, pri) {                     \
+#define hotplug_memory_notifier(fn, pri) ({            \
        static __meminitdata struct notifier_block fn##_mem_nb =\
-               { .notifier_call = fn, .priority = pri };       \
+               { .notifier_call = fn, .priority = pri };\
        register_memory_notifier(&fn##_mem_nb);                 \
-}
+})
+#define register_hotmemory_notifier(nb)                register_memory_notifier(nb)
+#define unregister_hotmemory_notifier(nb)      unregister_memory_notifier(nb)
 #else
-#define hotplug_memory_notifier(fn, pri) do { } while (0)
+#define hotplug_memory_notifier(fn, pri)       (0)
+/* These aren't inline functions due to a GCC bug. */
+#define register_hotmemory_notifier(nb)    ({ (void)(nb); 0; })
+#define unregister_hotmemory_notifier(nb)  ({ (void)(nb); })
 #endif
 
 /*
index d65746efc954c9b4f396a1bcf6561203de265fc9..d14a4c362465712857d1ea8fe39b974a5c05c4ce 100644 (file)
  * runtime initialization.
  */
 
+typedef        int (*notifier_fn_t)(struct notifier_block *nb,
+                       unsigned long action, void *data);
+
 struct notifier_block {
-       int (*notifier_call)(struct notifier_block *, unsigned long, void *);
+       notifier_fn_t notifier_call;
        struct notifier_block __rcu *next;
        int priority;
 };