Skip to contentSkip to conversation

writeback: show writeback reason with __print_symbolic

PATCH Superseded Wu Fengguang 3 participants 7 messages Dec 14, 2011 – Dec 15, 2011

Subsystems (3)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 writeback: show writeback reason with __print_symbolic

This makes the traces friendly to trace-cmd, at the cost of a bit code duplication.

CC Curt Wohlgemuth <[email protected]>
CC Steven Rostedt <[email protected]>
---
 include/trace/events/writeback.h |   17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)
include/trace/events/writeback.h +15 -2
@@ -21,6 +21,18 @@
 		{I_REFERENCED,		"I_REFERENCED"}		\
 	)
 
+#define show_work_reason(reason)					\
+	__print_symbolic(reason,					\
+		{WB_REASON_BACKGROUND,		"background"},		\
+		{WB_REASON_TRY_TO_FREE_PAGES,	"try_to_free_pages"},	\
+		{WB_REASON_SYNC,		"sync"},		\
+		{WB_REASON_PERIODIC,		"periodic"},		\
+		{WB_REASON_LAPTOP_TIMER,	"laptop_timer"},	\
+		{WB_REASON_FREE_MORE_MEM,	"free_more_memory"},	\
+		{WB_REASON_FS_FREE_SPACE,	"fs_free_space"},	\
+		{WB_REASON_FORKER_THREAD,	"forker_thread"}	\
+	)
+
 struct wb_writeback_work;
 
 DECLARE_EVENT_CLASS(writeback_work_class,
@@ -55,7 +67,7 @@ DECLARE_EVENT_CLASS(writeback_work_class
 		  __entry->for_kupdate,
 		  __entry->range_cyclic,
 		  __entry->for_background,
-		  wb_reason_name[__entry->reason]
+		  show_work_reason(__entry->reason)
 	)
 );
 #define DEFINE_WRITEBACK_WORK_EVENT(name) \
@@ -184,7 +196,8 @@ TRACE_EVENT(writeback_queue_io,
 		__entry->older,	/* older_than_this in jiffies */
 		__entry->age,	/* older_than_this in relative milliseconds */
 		__entry->moved,
-		wb_reason_name[__entry->reason])
+		show_work_reason(__entry->reason)
+	)
 );
 
 TRACE_EVENT(global_dirty_state,
maintainer
#1 lore raw

RFC PATCH 1/1 writeback: Unduplicate writeback reason

Names of the writeback reasons are used in both the main kernel as well as for parsing the tracepoint format file. Instead of duplicating the names in two locations making it likely that they may become out of sync, use some macro magic to make sure all the names stay in sync. Any update only needs to happen in one spot for it to take place in all locations.

Note, this is an RFC patch, and it probably needs much better comments (well, it currently has no comments), and the C() macro probably should have a different name too.

fs/fs-writeback.c +3 -8
Index: linux-trace.git/fs/fs-writeback.c
===================================================================
@@ -47,15 +47,10 @@ struct wb_writeback_work {
 	struct completion *done;	/* set if the caller waits */
 };
 
+#undef C
+#define C(a, b) [a] = b
 const char *wb_reason_name[] = {
-	[WB_REASON_BACKGROUND]		= "background",
-	[WB_REASON_TRY_TO_FREE_PAGES]	= "try_to_free_pages",
-	[WB_REASON_SYNC]		= "sync",
-	[WB_REASON_PERIODIC]		= "periodic",
-	[WB_REASON_LAPTOP_TIMER]	= "laptop_timer",
-	[WB_REASON_FREE_MORE_MEM]	= "free_more_memory",
-	[WB_REASON_FS_FREE_SPACE]	= "fs_free_space",
-	[WB_REASON_FORKER_THREAD]	= "forker_thread"
+	WB_ENUM_REASONS
 };
 
 /*
include/linux/writeback.h +13 -11
Index: linux-trace.git/include/linux/writeback.h
===================================================================
@@ -38,21 +38,23 @@ enum writeback_sync_modes {
 	WB_SYNC_ALL,	/* Wait on every mapping */
 };
 
+#define WB_ENUM_REASONS							\
+		C(WB_REASON_BACKGROUND,		"background"),		\
+		C(WB_REASON_TRY_TO_FREE_PAGES,	"try_to_free_pages"),	\
+		C(WB_REASON_SYNC,		"sync"),		\
+		C(WB_REASON_PERIODIC,		"periodic"),		\
+		C(WB_REASON_LAPTOP_TIMER,	"laptop_timer"),	\
+		C(WB_REASON_FREE_MORE_MEM,	"free_more_memory"),	\
+		C(WB_REASON_FS_FREE_SPACE,	"fs_free_space"),	\
+		C(WB_REASON_FORKER_THREAD,	"forker_thread")
+
 /*
  * why some writeback work was initiated
  */
-enum wb_reason {
-	WB_REASON_BACKGROUND,
-	WB_REASON_TRY_TO_FREE_PAGES,
-	WB_REASON_SYNC,
-	WB_REASON_PERIODIC,
-	WB_REASON_LAPTOP_TIMER,
-	WB_REASON_FREE_MORE_MEM,
-	WB_REASON_FS_FREE_SPACE,
-	WB_REASON_FORKER_THREAD,
+#undef C
+#define C(a, b) a
+enum wb_reason { WB_ENUM_REASONS, WB_REASONS_MAX };
 
-	WB_REASON_MAX,
-};
 extern const char *wb_reason_name[];
 
 /*
include/trace/events/writeback.h +3 -8
Index: linux-trace.git/include/trace/events/writeback.h
===================================================================
@@ -21,16 +21,11 @@
 		{I_REFERENCED,		"I_REFERENCED"}		\
 	)
 
+#undef C
+#define C(a, b) {a, b}
 #define show_work_reason(reason)					\
 	__print_symbolic(reason,					\
-		{WB_REASON_BACKGROUND,		"background"},		\
-		{WB_REASON_TRY_TO_FREE_PAGES,	"try_to_free_pages"},	\
-		{WB_REASON_SYNC,		"sync"},		\
-		{WB_REASON_PERIODIC,		"periodic"},		\
-		{WB_REASON_LAPTOP_TIMER,	"laptop_timer"},	\
-		{WB_REASON_FREE_MORE_MEM,	"free_more_memory"},	\
-		{WB_REASON_FS_FREE_SPACE,	"fs_free_space"},	\
-		{WB_REASON_FORKER_THREAD,	"forker_thread"}	\
+			 WB_ENUM_REASONS				\
 	)
 
 struct wb_writeback_work;
#2 lore raw

Re: [RFC][PATCH] writeback: Unduplicate writeback reason

Hi Steven,

Quoted 6 lines · Steven Rostedt

Names of the writeback reasons are used in both the main kernel as well as for parsing the tracepoint format file. Instead of duplicating the names in two locations making it likely that they may become out of sync, use some macro magic to make sure all the names stay in sync. Any update only needs to happen in one spot for it to take place in all locations.

It looks a bit hacky, but does the nice job of de-duplicating code. And it compiles. So I like it and would like to take it with the below rename :-)

Quoted 3 lines

Note, this is an RFC patch, and it probably needs much better comments (well, it currently has no comments), and the C() macro probably should have a different name too.

C => WB_ENUM_REASONS_ITEM? It may look unpleasantly long, however is unique enough to make the many #define/#undef safe.

Thanks!
Fengguang

Quoted 89 lines

Index: linux-trace.git/fs/fs-writeback.c
===================================================================

fs/fs-writeback.c +3 -8
@@ -47,15 +47,10 @@ struct wb_writeback_work {
 	struct completion *done;	/* set if the caller waits */
 };
 
+#undef C
+#define C(a, b) [a] = b
 const char *wb_reason_name[] = {
-	[WB_REASON_BACKGROUND]		= "background",
-	[WB_REASON_TRY_TO_FREE_PAGES]	= "try_to_free_pages",
-	[WB_REASON_SYNC]		= "sync",
-	[WB_REASON_PERIODIC]		= "periodic",
-	[WB_REASON_LAPTOP_TIMER]	= "laptop_timer",
-	[WB_REASON_FREE_MORE_MEM]	= "free_more_memory",
-	[WB_REASON_FS_FREE_SPACE]	= "fs_free_space",
-	[WB_REASON_FORKER_THREAD]	= "forker_thread"
+	WB_ENUM_REASONS
 };
 
 /*

Index: linux-trace.git/include/linux/writeback.h
===================================================================

include/linux/writeback.h +13 -11
@@ -38,21 +38,23 @@ enum writeback_sync_modes {
 	WB_SYNC_ALL,	/* Wait on every mapping */
 };
 
+#define WB_ENUM_REASONS							\
+		C(WB_REASON_BACKGROUND,		"background"),		\
+		C(WB_REASON_TRY_TO_FREE_PAGES,	"try_to_free_pages"),	\
+		C(WB_REASON_SYNC,		"sync"),		\
+		C(WB_REASON_PERIODIC,		"periodic"),		\
+		C(WB_REASON_LAPTOP_TIMER,	"laptop_timer"),	\
+		C(WB_REASON_FREE_MORE_MEM,	"free_more_memory"),	\
+		C(WB_REASON_FS_FREE_SPACE,	"fs_free_space"),	\
+		C(WB_REASON_FORKER_THREAD,	"forker_thread")
+
 /*
  * why some writeback work was initiated
  */
-enum wb_reason {
-	WB_REASON_BACKGROUND,
-	WB_REASON_TRY_TO_FREE_PAGES,
-	WB_REASON_SYNC,
-	WB_REASON_PERIODIC,
-	WB_REASON_LAPTOP_TIMER,
-	WB_REASON_FREE_MORE_MEM,
-	WB_REASON_FS_FREE_SPACE,
-	WB_REASON_FORKER_THREAD,
+#undef C
+#define C(a, b) a
+enum wb_reason { WB_ENUM_REASONS, WB_REASONS_MAX };
 
-	WB_REASON_MAX,
-};
 extern const char *wb_reason_name[];
 
 /*

Index: linux-trace.git/include/trace/events/writeback.h
===================================================================

include/trace/events/writeback.h +3 -8
@@ -21,16 +21,11 @@
 		{I_REFERENCED,		"I_REFERENCED"}		\
 	)
 
+#undef C
+#define C(a, b) {a, b}
 #define show_work_reason(reason)					\
 	__print_symbolic(reason,					\
-		{WB_REASON_BACKGROUND,		"background"},		\
-		{WB_REASON_TRY_TO_FREE_PAGES,	"try_to_free_pages"},	\
-		{WB_REASON_SYNC,		"sync"},		\
-		{WB_REASON_PERIODIC,		"periodic"},		\
-		{WB_REASON_LAPTOP_TIMER,	"laptop_timer"},	\
-		{WB_REASON_FREE_MORE_MEM,	"free_more_memory"},	\
-		{WB_REASON_FS_FREE_SPACE,	"fs_free_space"},	\
-		{WB_REASON_FORKER_THREAD,	"forker_thread"}	\
+			 WB_ENUM_REASONS				\
 	)
 
 struct wb_writeback_work;
maintainer
#3 lore raw

Re: [RFC][PATCH] writeback: Unduplicate writeback reason

Quoted 11 lines · Wu Fengguang

Hi Steven,

Quoted 6 lines · Steven Rostedt

Names of the writeback reasons are used in both the main kernel as well as for parsing the tracepoint format file. Instead of duplicating the names in two locations making it likely that they may become out of sync, use some macro magic to make sure all the names stay in sync. Any update only needs to happen in one spot for it to take place in all locations.

It looks a bit hacky,

One of my professors showed me this trick a long time ago when I was going for my Masters. It was actually the trick I based the entire TRACE_EVENT() macro magic on :)

Quoted 10 lines

but does the nice job of de-duplicating code.
And it compiles. So I like it and would like to take it with the below rename :-)

Quoted 3 lines

Note, this is an RFC patch, and it probably needs much better comments (well, it currently has no comments), and the C() macro probably should have a different name too.

C => WB_ENUM_REASONS_ITEM? It may look unpleasantly long, however is unique enough to make the many #define/#undef safe.

Sure. Acked-by: Steven Rostedt <[email protected]>

Note, there's one buggy issue still. That the enums names still trip up trace-cmd. But that's fine, because I have a plan to fix that too. But that will be on the ftrace said.

Thanks!

-- Steve

#4 lore raw

Re: [RFC][PATCH] writeback: Unduplicate writeback reason

In reply to Steven Rostedt
Quoted 10 lines · Steven Rostedt

Names of the writeback reasons are used in both the main kernel as well as for parsing the tracepoint format file. Instead of duplicating the names in two locations making it likely that they may become out of sync, use some macro magic to make sure all the names stay in sync. Any update only needs to happen in one spot for it to take place in all locations.

Note, this is an RFC patch, and it probably needs much better comments (well, it currently has no comments), and the C() macro probably should have a different name too.

I'm not sure this is a pattern we want to repeat all over the place - print_symbolic() is quite widely used and adding macro redefinitions all over the place doesn't fill me with joy.

AFAICT this code doesn't need a declared array to work so you can just use a preprocessor construct like this (as used in XFS):

#define value_1 1
#define value_2 2
.....

or

enum {
	value_1	= 1,
	value_2 = 2,
	.....
}

followed by:

#define VALUES	\
	{ value_1,	"Value 1" }, \
	{ value_2,	"Value 2" }, \
	.....

And it just uses print_symbolic(__entry->value, VALUES); to print them out.

If this construct does everything requiredi, then I think it is a much better pattern to use because it's easy to maintain, doesn't require an array to be declared in a C file and doesn't require macro tricks to do it's job....

Cheers,

Dave.

Signature · 2 lines
Dave Chinner
[email protected]
#5 lore raw

Re: [RFC][PATCH] writeback: Unduplicate writeback reason

Quoted 8 lines · Dave Chinner
Quoted 7 lines · Steven Rostedt

Names of the writeback reasons are used in both the main kernel as well as for parsing the tracepoint format file. Instead of duplicating the names in two locations making it likely that they may become out of sync, use some macro magic to make sure all the names stay in sync. Any update only needs to happen in one spot for it to take place in all locations.

Quoted 7 lines
Quoted 3 lines

Note, this is an RFC patch, and it probably needs much better comments (well, it currently has no comments), and the C() macro probably should have a different name too.

I'm not sure this is a pattern we want to repeat all over the place - print_symbolic() is quite widely used and adding macro redefinitions all over the place doesn't fill me with joy.

Yeah, unfortunately...

Quoted 1 line

AFAICT this code doesn't need a declared array to work so you can

You mean the string array wb_reason_name[]? Ah it's actually not used for now -- until there comes the (planned) writeback stats patch to show the reason names in some debugfs/sysfs interface.

So for the upcoming 3.2, wb_reason_name[] can be removed to avoid the duplication. However the question still remains how exactly are we going to re-introduce it in future?

Quoted 16 lines

just use a preprocessor construct like this (as used in XFS):

#define value_1 1
#define value_2 2
.....

or

enum {
	value_1	= 1,
	value_2 = 2,
	.....
}

followed by:

Quoted 7 lines
#define VALUES	\
	{ value_1,	"Value 1" }, \
	{ value_2,	"Value 2" }, \
	.....

And it just uses print_symbolic(__entry->value, VALUES); to print them out.

If using the above macros, wb_reason_name[] can be defined as

        static const struct trace_print_flags wb_reason_name[] = { VALUES };

and reference it in this way

        wb_reason_name[reason][1]

The first element is redundant info and will be ignored, because

        wb_reason_name[reason][0] == reason
Quoted 4 lines

If this construct does everything requiredi, then I think it is a much better pattern to use because it's easy to maintain, doesn't require an array to be declared in a C file and doesn't require macro tricks to do it's job....

Hmm, I looked through XFS tracing code and find no use case like the wb_reason_name[]. That is, the XFS symbolic names are only used for tracing output and there is no sharing with debugfs/sysfs outputs. So we may be talking about different situations.

Thanks,
Fengguang

#6 lore raw

Re: [RFC][PATCH] writeback: Unduplicate writeback reason

Quoted 17 lines · Wu Fengguang
Quoted 8 lines · Dave Chinner
Quoted 7 lines · Steven Rostedt

Names of the writeback reasons are used in both the main kernel as well as for parsing the tracepoint format file. Instead of duplicating the names in two locations making it likely that they may become out of sync, use some macro magic to make sure all the names stay in sync. Any update only needs to happen in one spot for it to take place in all locations.

Quoted 7 lines
Quoted 3 lines

Note, this is an RFC patch, and it probably needs much better comments (well, it currently has no comments), and the C() macro probably should have a different name too.

I'm not sure this is a pattern we want to repeat all over the place - print_symbolic() is quite widely used and adding macro redefinitions all over the place doesn't fill me with joy.

Quoted 7 lines

Yeah, unfortunately...

Quoted 1 line

AFAICT this code doesn't need a declared array to work so you can

You mean the string array wb_reason_name[]? Ah it's actually not used for now -- until there comes the (planned) writeback stats patch to show the reason names in some debugfs/sysfs interface.

Ah, ok. I missed that context.

.....

Quoted 14 lines
Quoted 9 lines

followed by:

#define VALUES	\
	{ value_1,	"Value 1" }, \
	{ value_2,	"Value 2" }, \
	.....

And it just uses print_symbolic(__entry->value, VALUES); to print them out.

If using the above macros, wb_reason_name[] can be defined as

        static const struct trace_print_flags wb_reason_name[] = { VALUES };
Quoted 7 lines

and reference it in this way

        wb_reason_name[reason][1]

The first element is redundant info and will be ignored, because

        wb_reason_name[reason][0] == reason

Yeah, that would work, and still place the definitions close together....

Quoted 9 lines
Quoted 5 lines

If this construct does everything requiredi, then I think it is a much better pattern to use because it's easy to maintain, doesn't require an array to be declared in a C file and doesn't require macro tricks to do it's job....

Hmm, I looked through XFS tracing code and find no use case like the wb_reason_name[]. That is, the XFS symbolic names are only used for tracing output and there is no sharing with debugfs/sysfs outputs.

Right. I didn't realise the writeback stuff was eventually going to be shared with sysfs. Still, it looks like it works better than playing macro redefinition games with you addition above, so perhaps it was best I didn't realise this in the first place. ;)

Cheers,

Dave.

Signature · 2 lines
Dave Chinner
[email protected]