Skip to contentSkip to conversation

Introduce and use printk pointer extension %pV

PATCH In review Joe Perches 3 participants 9 messages Jun 27, 2010 – Jul 4, 2010

Subsystems (5)
lore
Share & tools
lore
#1 lore raw

PATCH 1/4 vsprintf: Recursive vsnprintf: Add "%pV", struct va_format

In reply to Joe Perches

Add the ability to print a format and va_list from a structure pointer

Allows __dev_printk to be implemented as a single printk while minimizing string space duplication.

%pV should not be used without some mechanism to verify the format and argument use ala __attribute__(format (printf(...))).

---
 include/linux/kernel.h |    5 +++++
 lib/vsprintf.c         |    9 +++++++++
 2 files changed, 14 insertions(+), 0 deletions(-)
include/linux/kernel.h +5 -0
index 8317ec4..01dfc05 100644
@@ -171,6 +171,11 @@ static inline void might_fault(void)
 }
 #endif
 
+struct va_format {
+	const char *fmt;
+	va_list *va;
+};
+
 extern struct atomic_notifier_head panic_notifier_list;
 extern long (*panic_blink)(long time);
 NORET_TYPE void panic(const char * fmt, ...)
lib/vsprintf.c +9 -0
index b8a2f54..4ee19d0 100644
@@ -980,6 +980,11 @@ char *uuid_string(char *buf, char *end, const u8 *addr,
  *             [0][1][2][3]-[4][5]-[6][7]-[8][9]-[10][11][12][13][14][15]
  *           little endian output byte order is:
  *             [3][2][1][0]-[5][4]-[7][6]-[8][9]-[10][11][12][13][14][15]
+ * - 'V' For a struct va_format which contains a format string * and va_list *,
+ *       call vsnprintf(->format, *->va_list).
+ *       Implements a "recursive vsnprintf".
+ *       Do not use this feature without some mechanism to verify the
+ *       correctness of the format string and va_list arguments.
  *
  * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
  * function pointers are really function descriptors, which contain a
@@ -1025,6 +1030,10 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
 		break;
 	case 'U':
 		return uuid_string(buf, end, ptr, spec, fmt);
+	case 'V':
+		return buf + vsnprintf(buf, end - buf,
+				       ((struct va_format *)ptr)->fmt,
+				       *(((struct va_format *)ptr)->va));
 	}
 	spec.flags |= SMALL;
 	if (spec.field_width == -1) {
Signature · 1 line
1.7.1.337.g6068.dirty
#2 lore raw

PATCH 2/4 device.h drivers/base/core.c Convert dev_<level> logging macros to functions

In reply to Joe Perches

Reduces an x86 defconfig text and data ~55k, .6% smaller.

$ size vmlinux*
   text	   data	    bss	    dec	    hex	filename
7205273	 716016	1366288	9287577	 8db799	vmlinux
7258890	 719768	1366288	9344946	 8e97b2	vmlinux.master

Uses %pV and struct va_format
Format arguments are verified before printk

The dev_info macro is converted to _dev_info because there are existing uses of variables named dev_info in the kernel tree like drivers/net/pcmcia/pcnet_cs.c

A dev_info macro is created to call _dev_info

---
 drivers/base/core.c    |   64 +++++++++++++++++++++++++++
 include/linux/device.h |  112 ++++++++++++++++++++++++++++++++++++-----------
 2 files changed, 150 insertions(+), 26 deletions(-)
drivers/base/core.c +64 -0
index 9630fbd..38bbbd0 100644
@@ -1819,3 +1819,67 @@ void device_shutdown(void)
 	spin_unlock(&devices_kset->list_lock);
 	async_synchronize_full();
 }
+
+/*
+ * Device logging functions
+ */
+
+#ifdef CONFIG_PRINTK
+
+static int __dev_printk(const char *level, const struct device *dev,
+			struct va_format *vaf)
+{
+	if (!dev)
+		return printk("%s(NULL device *): %pV", level, vaf);
+
+	return printk("%s%s %s: %pV",
+		      level, dev_driver_string(dev), dev_name(dev), vaf);
+}
+
+int dev_printk(const char *level, const struct device *dev,
+	       const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+	int r;
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	r = __dev_printk(level, dev, &vaf);
+	va_end(args);
+
+	return r;
+}
+EXPORT_SYMBOL(dev_printk);
+
+#define define_dev_printk_level(func, kern_level)		\
+int func(const struct device *dev, const char *fmt, ...)	\
+{								\
+	struct va_format vaf;					\
+	va_list args;						\
+	int r;							\
+								\
+	va_start(args, fmt);					\
+								\
+	vaf.fmt = fmt;						\
+	vaf.va = &args;						\
+								\
+	r = __dev_printk(kern_level, dev, &vaf);		\
+	va_end(args);						\
+								\
+	return r;						\
+}								\
+EXPORT_SYMBOL(func);
+
+define_dev_printk_level(dev_emerg, KERN_EMERG);
+define_dev_printk_level(dev_alert, KERN_ALERT);
+define_dev_printk_level(dev_crit, KERN_CRIT);
+define_dev_printk_level(dev_err, KERN_ERR);
+define_dev_printk_level(dev_warn, KERN_WARNING);
+define_dev_printk_level(dev_notice, KERN_NOTICE);
+define_dev_printk_level(_dev_info, KERN_INFO);
+
+#endif
include/linux/device.h +86 -26

129 lines not on this page · raw message

Signature · 1 line
1.7.1.337.g6068.dirty
#3 lore raw

PATCH 3/4 netdevice.h net/core/dev.c: Convert netdev_<level> logging macros to functions

In reply to Joe Perches

Reduces an x86 defconfig text and data ~2k.
text is smaller, data is larger.

$ size vmlinux*
   text	   data	    bss	    dec	    hex	filename
7198862	 720112	1366288	9285262	 8dae8e	vmlinux
7205273	 716016	1366288	9287577	 8db799	vmlinux.device_h

Uses %pV and struct va_format
Format arguments are verified before printk

---
 include/linux/netdevice.h |   36 ++++++++++++-------------
 net/core/dev.c            |   62 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 79 insertions(+), 19 deletions(-)
include/linux/netdevice.h +17 -19
index 40291f3..7f3197d 100644
@@ -2227,25 +2227,23 @@ static inline const char *netdev_name(const struct net_device *dev)
 	return dev->name;
 }
 
-#define netdev_printk(level, netdev, format, args...)		\
-	dev_printk(level, (netdev)->dev.parent,			\
-		   "%s: " format,				\
-		   netdev_name(netdev), ##args)
-
-#define netdev_emerg(dev, format, args...)			\
-	netdev_printk(KERN_EMERG, dev, format, ##args)
-#define netdev_alert(dev, format, args...)			\
-	netdev_printk(KERN_ALERT, dev, format, ##args)
-#define netdev_crit(dev, format, args...)			\
-	netdev_printk(KERN_CRIT, dev, format, ##args)
-#define netdev_err(dev, format, args...)			\
-	netdev_printk(KERN_ERR, dev, format, ##args)
-#define netdev_warn(dev, format, args...)			\
-	netdev_printk(KERN_WARNING, dev, format, ##args)
-#define netdev_notice(dev, format, args...)			\
-	netdev_printk(KERN_NOTICE, dev, format, ##args)
-#define netdev_info(dev, format, args...)			\
-	netdev_printk(KERN_INFO, dev, format, ##args)
+extern int netdev_printk(const char *level, const struct net_device *dev,
+			 const char *format, ...)
+	__attribute__ ((format (printf, 3, 4)));
+extern int netdev_emerg(const struct net_device *dev, const char *format, ...)
+	__attribute__ ((format (printf, 2, 3)));
+extern int netdev_alert(const struct net_device *dev, const char *format, ...)
+	__attribute__ ((format (printf, 2, 3)));
+extern int netdev_crit(const struct net_device *dev, const char *format, ...)
+	__attribute__ ((format (printf, 2, 3)));
+extern int netdev_err(const struct net_device *dev, const char *format, ...)
+	__attribute__ ((format (printf, 2, 3)));
+extern int netdev_warn(const struct net_device *dev, const char *format, ...)
+	__attribute__ ((format (printf, 2, 3)));
+extern int netdev_notice(const struct net_device *dev, const char *format, ...)
+	__attribute__ ((format (printf, 2, 3)));
+extern int netdev_info(const struct net_device *dev, const char *format, ...)
+	__attribute__ ((format (printf, 2, 3)));
 
 #if defined(DEBUG)
 #define netdev_dbg(__dev, format, args...)			\
net/core/dev.c +62 -0

68 lines not on this page · raw message

Signature · 1 line
1.7.1.337.g6068.dirty
#0 lore raw

cover Introduce and use printk pointer extension %pV

Recursive printk can reduce the total image size of an x86 defconfig about 1% by reducing duplicated KERN_<level> strings and centralizing the functions used by macros in new separate functions.

Joe Perches (4):
vsprintf: Recursive vsnprintf: Add "%pV", struct va_format device.h drivers/base/core.c Convert dev_<level> logging macros to functions netdevice.h net/core/dev.c: Convert netdev_<level> logging macros to functions netdevice.h: Change netif_<level> macros to call netdev_<level> functions

 drivers/base/core.c       |   64 +++++++++++++++++++++++++
 include/linux/device.h    |  112 ++++++++++++++++++++++++++++++++++----------
 include/linux/kernel.h    |    5 ++
 include/linux/netdevice.h |   56 ++++++++++++----------
 lib/vsprintf.c            |    9 ++++
 net/core/dev.c            |   62 +++++++++++++++++++++++++
 6 files changed, 256 insertions(+), 52 deletions(-)
#4 lore raw

PATCH 4/4 netdevice.h: Change netif_<level> macros to call netdev_<level> functions

Reduces text ~300 bytes of text (woohoo!) in an x86 defconfig

$ size vmlinux*
   text	   data	    bss	    dec	    hex	filename
7198526	 720112	1366288	9284926	 8dad3e	vmlinux
7198862	 720112	1366288	9285262	 8dae8e	vmlinux.netdev
---
 include/linux/netdevice.h |   20 +++++++++++++-------
 1 files changed, 13 insertions(+), 7 deletions(-)
include/linux/netdevice.h +13 -7
index 7f3197d..489a612 100644
@@ -2291,20 +2291,26 @@ do {					  			\
 		netdev_printk(level, (dev), fmt, ##args);	\
 } while (0)
 
+#define netif_level(level, priv, type, dev, fmt, args...)	\
+do {								\
+	if (netif_msg_##type(priv))				\
+		netdev_##level(dev, fmt, ##args);		\
+} while (0)
+
 #define netif_emerg(priv, type, dev, fmt, args...)		\
-	netif_printk(priv, type, KERN_EMERG, dev, fmt, ##args)
+	netif_level(emerg, priv, type, dev, fmt, ##args)
 #define netif_alert(priv, type, dev, fmt, args...)		\
-	netif_printk(priv, type, KERN_ALERT, dev, fmt, ##args)
+	netif_level(alert, priv, type, dev, fmt, ##args)
 #define netif_crit(priv, type, dev, fmt, args...)		\
-	netif_printk(priv, type, KERN_CRIT, dev, fmt, ##args)
+	netif_level(crit, priv, type, dev, fmt, ##args)
 #define netif_err(priv, type, dev, fmt, args...)		\
-	netif_printk(priv, type, KERN_ERR, dev, fmt, ##args)
+	netif_level(err, priv, type, dev, fmt, ##args)
 #define netif_warn(priv, type, dev, fmt, args...)		\
-	netif_printk(priv, type, KERN_WARNING, dev, fmt, ##args)
+	netif_level(warn, priv, type, dev, fmt, ##args)
 #define netif_notice(priv, type, dev, fmt, args...)		\
-	netif_printk(priv, type, KERN_NOTICE, dev, fmt, ##args)
+	netif_level(notice, priv, type, dev, fmt, ##args)
 #define netif_info(priv, type, dev, fmt, args...)		\
-	netif_printk(priv, type, KERN_INFO, (dev), fmt, ##args)
+	netif_level(info, priv, type, dev, fmt, ##args)
 
 #if defined(DEBUG)
 #define netif_dbg(priv, type, dev, format, args...)		\
Signature · 1 line
1.7.1.337.g6068.dirty
maintainer
#5 lore raw
In reply to Joe Perches

From: Joe Perches <[email protected]>
Date: Sun, 27 Jun 2010 04:02:32 -0700

Quoted 9 lines

Recursive printk can reduce the total image size of an x86 defconfig about 1% by reducing duplicated KERN_<level> strings and centralizing the functions used by macros in new separate functions.

Joe Perches (4):
vsprintf: Recursive vsnprintf: Add "%pV", struct va_format device.h drivers/base/core.c Convert dev_<level> logging macros to functions netdevice.h net/core/dev.c: Convert netdev_<level> logging macros to functions netdevice.h: Change netif_<level> macros to call netdev_<level> functions

I'm fine with this, thanks Joe.

Greg, could you ACK this and let me know if it's OK if it swings through my net-next-2.6 tree?

Thanks.

maintainer
#6 lore raw

From: David Miller <[email protected]>
Date: Wed, 30 Jun 2010 13:07:09 -0700 (PDT)

Quoted 13 lines

From: Joe Perches <[email protected]>
Date: Sun, 27 Jun 2010 04:02:32 -0700

Quoted 9 lines

Recursive printk can reduce the total image size of an x86 defconfig about 1% by reducing duplicated KERN_<level> strings and centralizing the functions used by macros in new separate functions.

Joe Perches (4):
vsprintf: Recursive vsnprintf: Add "%pV", struct va_format device.h drivers/base/core.c Convert dev_<level> logging macros to functions netdevice.h net/core/dev.c: Convert netdev_<level> logging macros to functions netdevice.h: Change netif_<level> macros to call netdev_<level> functions

Quoted 4 lines

I'm fine with this, thanks Joe.

Greg, could you ACK this and let me know if it's OK if it swings through my net-next-2.6 tree?

Greg, ping?

Acked-by Greg Kroah-Hartman
#7 lore raw
Quoted 16 lines · David Miller

From: David Miller <[email protected]>
Date: Wed, 30 Jun 2010 13:07:09 -0700 (PDT)

Quoted 13 lines

From: Joe Perches <[email protected]>
Date: Sun, 27 Jun 2010 04:02:32 -0700

Quoted 9 lines

Recursive printk can reduce the total image size of an x86 defconfig about 1% by reducing duplicated KERN_<level> strings and centralizing the functions used by macros in new separate functions.

Joe Perches (4):
vsprintf: Recursive vsnprintf: Add "%pV", struct va_format device.h drivers/base/core.c Convert dev_<level> logging macros to functions netdevice.h net/core/dev.c: Convert netdev_<level> logging macros to functions netdevice.h: Change netif_<level> macros to call netdev_<level> functions

Quoted 6 lines
Quoted 4 lines

I'm fine with this, thanks Joe.

Greg, could you ACK this and let me know if it's OK if it swings through my net-next-2.6 tree?

Greg, ping?

Sorry about the delay.

Yes, that's fine to take it through your tree, thanks for doing that:

greg k-h

maintainer
#8 lore raw

From: Greg KH <[email protected]>
Date: Sat, 3 Jul 2010 09:08:57 -0700

Quoted 22 lines · David Miller
Quoted 21 lines

From: David Miller <[email protected]>
Date: Wed, 30 Jun 2010 13:07:09 -0700 (PDT)

Quoted 17 lines

From: Joe Perches <[email protected]>
Date: Sun, 27 Jun 2010 04:02:32 -0700

Quoted 9 lines

Recursive printk can reduce the total image size of an x86 defconfig about 1% by reducing duplicated KERN_<level> strings and centralizing the functions used by macros in new separate functions.

Joe Perches (4):
vsprintf: Recursive vsnprintf: Add "%pV", struct va_format device.h drivers/base/core.c Convert dev_<level> logging macros to functions netdevice.h net/core/dev.c: Convert netdev_<level> logging macros to functions netdevice.h: Change netif_<level> macros to call netdev_<level> functions

I'm fine with this, thanks Joe.

Greg, could you ACK this and let me know if it's OK if it swings through my net-next-2.6 tree?

Quoted 6 lines
Quoted 1 line

Greg, ping?

Sorry about the delay.

Yes, that's fine to take it through your tree, thanks for doing that:

Thanks! I've added this set to my tree.