[PATCH v4] modules: wait do_free_init correctly

2024-02-26 Thread Changbin Du
The synchronization here is to ensure the ordering of freeing of a module
init so that it happens before W+X checking. It is worth noting it is not
that the freeing was not happening, it is just that our sanity checkers
raced against the permission checkers which assume init memory is already
gone.

Commit 1a7b7d922081 ("modules: Use vmalloc special flag") moved
calling do_free_init() into a global workqueue instead of relying on it
being called through call_rcu(..., do_free_init), which used to allowed us
call do_free_init() asynchronously after the end of a subsequent grace
period. The move to a global workqueue broke the gaurantees for code which
needed to be sure the do_free_init() would complete with rcu_barrier().
To fix this callers which used to rely on rcu_barrier() must now instead
use flush_work(&init_free_wq).

Without this fix, we still could encounter false positive reports in W+X
checking since the rcu_barrier() here can not ensure the ordering now.

Even worse, the rcu_barrier() can introduce significant delay. Eric Chanudet
reported that the rcu_barrier introduces ~0.1s delay on a PREEMPT_RT kernel.

  [0.291444] Freeing unused kernel memory: 5568K
  [0.402442] Run /sbin/init as init process

With this fix, the above delay can be eliminated.

Fixes: 1a7b7d922081 ("modules: Use vmalloc special flag")
Signed-off-by: Changbin Du 
Cc: Xiaoyi Su 
Cc: Eric Chanudet 
Cc: Luis Chamberlain 
Tested-by: Eric Chanudet 

---
v4:
  - polish commit msg. (Luis Chamberlain)
v3:
  - amend comment in do_init_module() and update commit msg.
v2:
  - fix compilation issue for no CONFIG_MODULES found by 0-DAY.
---
 include/linux/moduleloader.h | 8 
 init/main.c  | 5 +++--
 kernel/module/main.c | 9 +++--
 3 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/include/linux/moduleloader.h b/include/linux/moduleloader.h
index 001b2ce83832..89b1e0ed9811 100644
--- a/include/linux/moduleloader.h
+++ b/include/linux/moduleloader.h
@@ -115,6 +115,14 @@ int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
struct module *mod);
 
+#ifdef CONFIG_MODULES
+void flush_module_init_free_work(void);
+#else
+static inline void flush_module_init_free_work(void)
+{
+}
+#endif
+
 /* Any cleanup needed when module leaves. */
 void module_arch_cleanup(struct module *mod);
 
diff --git a/init/main.c b/init/main.c
index e24b0780fdff..f0b7e21ac67f 100644
--- a/init/main.c
+++ b/init/main.c
@@ -99,6 +99,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -1402,11 +1403,11 @@ static void mark_readonly(void)
if (rodata_enabled) {
/*
 * load_module() results in W+X mappings, which are cleaned
-* up with call_rcu().  Let's make sure that queued work is
+* up with init_free_wq. Let's make sure that queued work is
 * flushed so that we don't hit false positives looking for
 * insecure pages which are W+X.
 */
-   rcu_barrier();
+   flush_module_init_free_work();
mark_rodata_ro();
rodata_test();
} else
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 36681911c05a..b0b99348e1a8 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -2489,6 +2489,11 @@ static void do_free_init(struct work_struct *w)
}
 }
 
+void flush_module_init_free_work(void)
+{
+   flush_work(&init_free_wq);
+}
+
 #undef MODULE_PARAM_PREFIX
 #define MODULE_PARAM_PREFIX "module."
 /* Default value for module->async_probe_requested */
@@ -2593,8 +2598,8 @@ static noinline int do_init_module(struct module *mod)
 * Note that module_alloc() on most architectures creates W+X page
 * mappings which won't be cleaned up until do_free_init() runs.  Any
 * code such as mark_rodata_ro() which depends on those mappings to
-* be cleaned up needs to sync with the queued work - ie
-* rcu_barrier()
+* be cleaned up needs to sync with the queued work by invoking
+* flush_module_init_free_work().
 */
if (llist_add(&freeinit->node, &init_free_list))
schedule_work(&init_free_wq);
-- 
2.25.1




Re: [PATCH v3] modules: wait do_free_init correctly

2024-02-22 Thread Changbin Du
On Wed, Feb 21, 2024 at 09:40:48AM -0800, Luis Chamberlain wrote:
> + live-patching folks,
> 
> Finally, things are starting to be much clearer. Thanks for the time
> for working on this, some more comments below and a question which
> I think deserves some attention.
> 
> On Sat, Feb 17, 2024 at 04:18:10PM +0800, Changbin Du wrote:
> > The synchronization here is just to ensure the module init's been freed
> > before doing W+X checking. 
> 
> Some nits, this should read instead:
> 
> Fix the ordering of freeing of a module init so that it happens before
> W+X checking.
> 
> > But the commit 1a7b7d922081 ("modules: Use
> > vmalloc special flag") moves do_free_init() into a global workqueue
> > instead of call_rcu(). So now rcu_barrier() can not ensure that do_free_init
> > has completed. We should wait it via flush_work().
> 
> Remove "But" and adjust as:
> 
> Commit 1a7b7d922081 ("modules: Use vmalloc special flag") moved
> calling do_free_init() into a global workqueue instead of relying on it
> being called through call_rcu(..., do_free_init), which used to allowed us
> call do_free_init() asynchronously after the end of a subsequent grace
>  
> period. The move to a global workqueue broke the gaurantees for code
> which needed to be sure the do_free_init() would complete with rcu_barrier().
> To fix this callers which used to rely on rcu_barrier() must now instead
> use flush_work(&init_free_wq).
>
Sure, thanks!

> > Without this fix, we still could encounter false positive reports in
> > W+X checking,
> 
> This is good thanks for the clarification.
> 
> I think it would be useful for the commit log then to describe also that
> it is not that the freeing was not happening, it is just that our sanity
> checkers raced against the permission checkers which assume init memory
> is already gone.
> 
okay, I'll apend this detailed explanation.

> > and the rcu synchronization is unnecessary which can
> > introduce significant delay.
> 
> While this can be true, I am not sure if we can remove it. See below.
> 
> > Eric Chanudet reports that the rcu_barrier introduces ~0.1s delay on a
> > PREEMPT_RT kernel.
> 
> That's a separate issue.
> 
> >   [0.291444] Freeing unused kernel memory: 5568K
> >   [0.402442] Run /sbin/init as init process
> > 
> > With this fix, the above delay can be eliminated.
> > 
> > Fixes: 1a7b7d922081 ("modules: Use vmalloc special flag")
> > Signed-off-by: Changbin Du 
> > Cc: Xiaoyi Su 
> > Cc: Eric Chanudet 
> > 
> > ---
> > v3:
> >   - amend comment in do_init_module() and update commit msg.
> > v2:
> >   - fix compilation issue for no CONFIG_MODULES found by 0-DAY.
> > ---
> >  include/linux/moduleloader.h | 8 
> >  init/main.c  | 5 +++--
> >  kernel/module/main.c | 9 +++--
> >  3 files changed, 18 insertions(+), 4 deletions(-)
> > 
> > diff --git a/include/linux/moduleloader.h b/include/linux/moduleloader.h
> > index 001b2ce83832..89b1e0ed9811 100644
> > --- a/include/linux/moduleloader.h
> > +++ b/include/linux/moduleloader.h
> > @@ -115,6 +115,14 @@ int module_finalize(const Elf_Ehdr *hdr,
> > const Elf_Shdr *sechdrs,
> > struct module *mod);
> >  
> > +#ifdef CONFIG_MODULES
> > +void flush_module_init_free_work(void);
> > +#else
> > +static inline void flush_module_init_free_work(void)
> > +{
> > +}
> > +#endif
> > +
> >  /* Any cleanup needed when module leaves. */
> >  void module_arch_cleanup(struct module *mod);
> >  
> > diff --git a/init/main.c b/init/main.c
> > index e24b0780fdff..f0b7e21ac67f 100644
> > --- a/init/main.c
> > +++ b/init/main.c
> > @@ -99,6 +99,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  
> >  #include 
> > @@ -1402,11 +1403,11 @@ static void mark_readonly(void)
> > if (rodata_enabled) {
> > /*
> >  * load_module() results in W+X mappings, which are cleaned
> > -* up with call_rcu().  Let's make sure that queued work is
> > +* up with init_free_wq. Let's make sure that queued work is
> >  * flushed so that we don't hit false positives looking for
> >  * insecure pages which are W+X.
> >  */
> > -   rcu_barrier();
> 
> Was this the only source of waiters that used rcu_barrier() to sync ?
> What about

[PATCH v3] modules: wait do_free_init correctly

2024-02-17 Thread Changbin Du
The synchronization here is just to ensure the module init's been freed
before doing W+X checking. But the commit 1a7b7d922081 ("modules: Use
vmalloc special flag") moves do_free_init() into a global workqueue
instead of call_rcu(). So now rcu_barrier() can not ensure that do_free_init
has completed. We should wait it via flush_work().

Without this fix, we still could encounter false positive reports in
W+X checking, and the rcu synchronization is unnecessary which can
introduce significant delay.

Eric Chanudet reports that the rcu_barrier introduces ~0.1s delay on a
PREEMPT_RT kernel.
  [0.291444] Freeing unused kernel memory: 5568K
  [0.402442] Run /sbin/init as init process

With this fix, the above delay can be eliminated.

Fixes: 1a7b7d922081 ("modules: Use vmalloc special flag")
Signed-off-by: Changbin Du 
Cc: Xiaoyi Su 
Cc: Eric Chanudet 

---
v3:
  - amend comment in do_init_module() and update commit msg.
v2:
  - fix compilation issue for no CONFIG_MODULES found by 0-DAY.
---
 include/linux/moduleloader.h | 8 
 init/main.c  | 5 +++--
 kernel/module/main.c | 9 +++--
 3 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/include/linux/moduleloader.h b/include/linux/moduleloader.h
index 001b2ce83832..89b1e0ed9811 100644
--- a/include/linux/moduleloader.h
+++ b/include/linux/moduleloader.h
@@ -115,6 +115,14 @@ int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
struct module *mod);
 
+#ifdef CONFIG_MODULES
+void flush_module_init_free_work(void);
+#else
+static inline void flush_module_init_free_work(void)
+{
+}
+#endif
+
 /* Any cleanup needed when module leaves. */
 void module_arch_cleanup(struct module *mod);
 
diff --git a/init/main.c b/init/main.c
index e24b0780fdff..f0b7e21ac67f 100644
--- a/init/main.c
+++ b/init/main.c
@@ -99,6 +99,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -1402,11 +1403,11 @@ static void mark_readonly(void)
if (rodata_enabled) {
/*
 * load_module() results in W+X mappings, which are cleaned
-* up with call_rcu().  Let's make sure that queued work is
+* up with init_free_wq. Let's make sure that queued work is
 * flushed so that we don't hit false positives looking for
 * insecure pages which are W+X.
 */
-   rcu_barrier();
+   flush_module_init_free_work();
mark_rodata_ro();
rodata_test();
} else
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 36681911c05a..b0b99348e1a8 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -2489,6 +2489,11 @@ static void do_free_init(struct work_struct *w)
}
 }
 
+void flush_module_init_free_work(void)
+{
+   flush_work(&init_free_wq);
+}
+
 #undef MODULE_PARAM_PREFIX
 #define MODULE_PARAM_PREFIX "module."
 /* Default value for module->async_probe_requested */
@@ -2593,8 +2598,8 @@ static noinline int do_init_module(struct module *mod)
 * Note that module_alloc() on most architectures creates W+X page
 * mappings which won't be cleaned up until do_free_init() runs.  Any
 * code such as mark_rodata_ro() which depends on those mappings to
-* be cleaned up needs to sync with the queued work - ie
-* rcu_barrier()
+* be cleaned up needs to sync with the queued work by invoking
+* flush_module_init_free_work().
 */
if (llist_add(&freeinit->node, &init_free_list))
schedule_work(&init_free_wq);
-- 
2.25.1




Re: [RESEND PATCH v2] modules: wait do_free_init correctly

2024-02-17 Thread Changbin Du
On Thu, Feb 15, 2024 at 09:18:09AM -0500, Eric Chanudet wrote:
> On Tue, Jan 30, 2024 at 06:21:03AM -0800, Luis Chamberlain wrote:
> > On Tue, Jan 30, 2024 at 09:40:38AM +0800, Changbin Du wrote:
> > > On Mon, Jan 29, 2024 at 09:53:58AM -0800, Luis Chamberlain wrote:
> > > > On Mon, Jan 29, 2024 at 10:03:04AM +0800, Changbin Du wrote:
> > > > > The commit 1a7b7d922081 ("modules: Use vmalloc special flag") moves
> > > > > do_free_init() into a global workqueue instead of call_rcu(). So now
> > > > > rcu_barrier() can not ensure that do_free_init has completed. We 
> > > > > should
> > > > > wait it via flush_work().
> > > > > 
> > > > > Without this fix, we still could encounter false positive reports in
> > > > > W+X checking, and rcu synchronization is unnecessary.
> 
> The comment in do_init_module(), just before
> schedule_work(&init_free_wq), mentioning rcu_barrier(), should be
> amended as well.
>
yes, I'll update it as well.

> > > > 
> > > > You didn't answer my question, which should be documented in the commit 
> > > > log.
> > > > 
> > > > Does this mean we never freed modules init because of this? If so then
> > > > your commit log should clearly explain that. It should also explain that
> > > > if true (you have to verify) then it means we were no longer saving
> > > > the memory we wished to save, and that is important for distributions
> > > > which do want to save anything on memory. You may want to do a general
> > > > estimate on how much that means these days on any desktop / server.
> > >
> > > Actually, I have explained it in commit msg. It's not about saving 
> > > memory. The
> > > synchronization here is just to ensure the module init's been freed before
> > > doing W+X checking. The problem is that the current implementation is 
> > > wrong,
> > > rcu_barrier() cannot guarantee that. So we can encounter false positive 
> > > reports.
> > > But anyway, the module init will be freed, and it's just a timing related 
> > > issue.
> > 
> > Your desciption here is better than the commit log.
> 
> I saw this problem using a PREEMPT_RT kernel as well. Setting DEBUG_WX=n
> stills show a significant delay due to the rcu_barrier:
>   [0.291444] Freeing unused kernel memory: 5568K
>   [0.402442] Run /sbin/init as init process
> 
> The same delay is shorter using linux-next, but still noticeable
> (DEBUG_WX=n):
>   [0.384362] Freeing unused kernel memory: 14080K
>   [0.413423] Run /sbin/init as init process
> 
> Matching trace_event=rcu:rcu_barrier trace:
>  systemd-1   [002] . 0.384391: rcu_barrier: rcu_preempt 
> Begin cpu -1 remaining 0 # 4
>  systemd-1   [002] d..1. 0.384394: rcu_barrier: rcu_preempt 
> Inc1 cpu -1 remaining 0 # 1
>  systemd-1   [002] . 0.384395: rcu_barrier: rcu_preempt 
> NQ cpu 0 remaining 2 # 1
>   -0   [001] d.h2. 0.384407: rcu_barrier: rcu_preempt 
> IRQ cpu -1 remaining 2 # 1
>  systemd-1   [002] . 0.384408: rcu_barrier: rcu_preempt 
> OnlineQ cpu 1 remaining 3 # 1
>  systemd-1   [002] . 0.384409: rcu_barrier: rcu_preempt 
> NQ cpu 2 remaining 3 # 1
>   -0   [003] d.h2. 0.384416: rcu_barrier: rcu_preempt 
> IRQ cpu -1 remaining 3 # 1
>  systemd-1   [002] . 0.384418: rcu_barrier: rcu_preempt 
> OnlineQ cpu 3 remaining 4 # 1
>   -0   [004] d.h2. 0.384428: rcu_barrier: rcu_preempt 
> IRQ cpu -1 remaining 4 # 1
>  systemd-1   [002] . 0.384430: rcu_barrier: rcu_preempt 
> OnlineQ cpu 4 remaining 5 # 1
>   -0   [005] d.h2. 0.384438: rcu_barrier: rcu_preempt 
> IRQ cpu -1 remaining 5 # 1
>  systemd-1   [002] . 0.384441: rcu_barrier: rcu_preempt 
> OnlineQ cpu 5 remaining 6 # 1
>   -0   [006] d.h2. 0.384450: rcu_barrier: rcu_preempt 
> IRQ cpu -1 remaining 6 # 1
>  systemd-1   [002] . 0.384452: rcu_barrier: rcu_preempt 
> OnlineQ cpu 6 remaining 7 # 1
>   -0   [007] d.h2. 0.384461: rcu_barrier: rcu_preempt 
> IRQ cpu -1 remaining 7 # 1
>  systemd-1   [002] . 0.384463: rcu_barrier: rcu_preempt 
> OnlineQ cpu 7 remaining 8 # 1
>   -0   [004] ..s1. 0.385339: rcu_barrier: rcu_preempt 
> CB cpu -1 remaining 5 # 1
>   -0   [007] ..s1. 0.397335: rcu_barrier: rcu_preempt 
> CB cpu -1 remain

Re: [RESEND PATCH v2] modules: wait do_free_init correctly

2024-01-29 Thread Changbin Du
On Mon, Jan 29, 2024 at 09:53:58AM -0800, Luis Chamberlain wrote:
> On Mon, Jan 29, 2024 at 10:03:04AM +0800, Changbin Du wrote:
> > The commit 1a7b7d922081 ("modules: Use vmalloc special flag") moves
> > do_free_init() into a global workqueue instead of call_rcu(). So now
> > rcu_barrier() can not ensure that do_free_init has completed. We should
> > wait it via flush_work().
> > 
> > Without this fix, we still could encounter false positive reports in
> > W+X checking, and rcu synchronization is unnecessary.
> 
> You didn't answer my question, which should be documented in the commit log.
> 
> Does this mean we never freed modules init because of this? If so then
> your commit log should clearly explain that. It should also explain that
> if true (you have to verify) then it means we were no longer saving
> the memory we wished to save, and that is important for distributions
> which do want to save anything on memory. You may want to do a general
> estimate on how much that means these days on any desktop / server.
>
Actually, I have explained it in commit msg. It's not about saving memory. The
synchronization here is just to ensure the module init's been freed before
doing W+X checking. The problem is that the current implementation is wrong,
rcu_barrier() cannot guarantee that. So we can encounter false positive reports.
But anyway, the module init will be freed, and it's just a timing related issue.

>   Luis

-- 
Cheers,
Changbin Du



[RESEND PATCH v2] modules: wait do_free_init correctly

2024-01-28 Thread Changbin Du
The commit 1a7b7d922081 ("modules: Use vmalloc special flag") moves
do_free_init() into a global workqueue instead of call_rcu(). So now
rcu_barrier() can not ensure that do_free_init has completed. We should
wait it via flush_work().

Without this fix, we still could encounter false positive reports in
W+X checking, and rcu synchronization is unnecessary.

Fixes: 1a7b7d922081 ("modules: Use vmalloc special flag")
Signed-off-by: Changbin Du 
Cc: Xiaoyi Su 

---
v2: fix compilation issue for no CONFIG_MODULES found by 0-DAY.
---
 include/linux/moduleloader.h | 8 
 init/main.c  | 5 +++--
 kernel/module/main.c | 5 +
 3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/include/linux/moduleloader.h b/include/linux/moduleloader.h
index 001b2ce83832..89b1e0ed9811 100644
--- a/include/linux/moduleloader.h
+++ b/include/linux/moduleloader.h
@@ -115,6 +115,14 @@ int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
struct module *mod);
 
+#ifdef CONFIG_MODULES
+void flush_module_init_free_work(void);
+#else
+static inline void flush_module_init_free_work(void)
+{
+}
+#endif
+
 /* Any cleanup needed when module leaves. */
 void module_arch_cleanup(struct module *mod);
 
diff --git a/init/main.c b/init/main.c
index e24b0780fdff..f0b7e21ac67f 100644
--- a/init/main.c
+++ b/init/main.c
@@ -99,6 +99,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -1402,11 +1403,11 @@ static void mark_readonly(void)
if (rodata_enabled) {
/*
 * load_module() results in W+X mappings, which are cleaned
-* up with call_rcu().  Let's make sure that queued work is
+* up with init_free_wq. Let's make sure that queued work is
 * flushed so that we don't hit false positives looking for
 * insecure pages which are W+X.
 */
-   rcu_barrier();
+   flush_module_init_free_work();
mark_rodata_ro();
rodata_test();
} else
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 36681911c05a..ea66b5c2a2a1 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -2489,6 +2489,11 @@ static void do_free_init(struct work_struct *w)
}
 }
 
+void flush_module_init_free_work(void)
+{
+   flush_work(&init_free_wq);
+}
+
 #undef MODULE_PARAM_PREFIX
 #define MODULE_PARAM_PREFIX "module."
 /* Default value for module->async_probe_requested */
-- 
2.25.1




[PATCH v2] modules: wait do_free_init correctly

2023-12-24 Thread Changbin Du
The commit 1a7b7d922081 ("modules: Use vmalloc special flag") moves
do_free_init() into a global workqueue instead of call_rcu(). So now
rcu_barrier() can not ensure that do_free_init has completed. We should
wait it via flush_work().

Without this fix, we still could encounter false positive reports in
W+X checking.

Fixes: 1a7b7d922081 ("modules: Use vmalloc special flag")
Signed-off-by: Changbin Du 
Cc: Xiaoyi Su 

---
v2: fix compilation issue for no CONFIG_MODULES found by 0-DAY.
---
 include/linux/moduleloader.h | 8 
 init/main.c  | 5 +++--
 kernel/module/main.c | 5 +
 3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/include/linux/moduleloader.h b/include/linux/moduleloader.h
index 001b2ce83832..89b1e0ed9811 100644
--- a/include/linux/moduleloader.h
+++ b/include/linux/moduleloader.h
@@ -115,6 +115,14 @@ int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
struct module *mod);
 
+#ifdef CONFIG_MODULES
+void flush_module_init_free_work(void);
+#else
+static inline void flush_module_init_free_work(void)
+{
+}
+#endif
+
 /* Any cleanup needed when module leaves. */
 void module_arch_cleanup(struct module *mod);
 
diff --git a/init/main.c b/init/main.c
index e24b0780fdff..f0b7e21ac67f 100644
--- a/init/main.c
+++ b/init/main.c
@@ -99,6 +99,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -1402,11 +1403,11 @@ static void mark_readonly(void)
if (rodata_enabled) {
/*
 * load_module() results in W+X mappings, which are cleaned
-* up with call_rcu().  Let's make sure that queued work is
+* up with init_free_wq. Let's make sure that queued work is
 * flushed so that we don't hit false positives looking for
 * insecure pages which are W+X.
 */
-   rcu_barrier();
+   flush_module_init_free_work();
mark_rodata_ro();
rodata_test();
} else
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 98fedfdb8db5..1943ccb7414f 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -2486,6 +2486,11 @@ static void do_free_init(struct work_struct *w)
}
 }
 
+void flush_module_init_free_work(void)
+{
+   flush_work(&init_free_wq);
+}
+
 #undef MODULE_PARAM_PREFIX
 #define MODULE_PARAM_PREFIX "module."
 /* Default value for module->async_probe_requested */
-- 
2.25.1




Re: [PATCH] modules: wait do_free_init correctly

2023-12-24 Thread Changbin Du
On Thu, Dec 21, 2023 at 10:30:37AM +0800, Changbin Du wrote:
> On Wed, Dec 20, 2023 at 06:32:39AM -0800, Luis Chamberlain wrote:
> > On Wed, Dec 20, 2023 at 01:27:51PM +0800, Changbin Du wrote:
> > > On Tue, Dec 19, 2023 at 01:52:03PM -0800, Luis Chamberlain wrote:
> > > > On Tue, Dec 19, 2023 at 12:51:51PM -0800, Andrew Morton wrote:
> > > > > On Tue, 19 Dec 2023 22:12:31 +0800 Changbin Du 
> > > > >  wrote:
> > > > > 
> > > > > > The commit 1a7b7d922081 ("modules: Use vmalloc special flag") moves
> > > > > > do_free_init() into a global workqueue instead of call_rcu(). So now
> > > > > > we should wait it via flush_work().
> > > > > 
> > > > > What are the runtime effects of this change?
> > > > 
> > > > Indeed that's needed given how old this culprit commit is:
> > > > 
> > > > git describe --contains 1a7b7d922081
> > > > v5.2-rc1~192^2~5
> > > > 
> > > > Who did this work and for what reason? What triggered this itch?
> > > >
> > > Seems the waiting was introduced by commit ae646f0b9ca ("init: fix false 
> > > positives
> > > in W+X checking").
> > > 
> > > As what I have observed, mark_readonly() is only invoked by the first 
> > > user mode
> > > thread function kernel_init(), which is before userspace /init. So is it 
> > > real
> > > possible we have loaded modules at this point?
> > 
> > Are you saying we don't free any module inits at all then? I asked a lot
> > of questions and your answers seem slim.
> >
> Yes, indeed no module loaded at all before mark_readonly(), at least on my 
> desktop.
> So I think we can just delete this synchronization. I am not sure whether 
> there are
> any historical reasons.
>
I thought about it again, kernel doesn't prevent any drivers from calling
request_module() before init. So it's possible that some particular modules do
behave this way.

I will send an updated one to fix the compilation issue for no CONFIG_MODULES.

-- 
Cheers,
Changbin Du



Re: [PATCH] modules: wait do_free_init correctly

2023-12-20 Thread Changbin Du
On Wed, Dec 20, 2023 at 06:32:39AM -0800, Luis Chamberlain wrote:
> On Wed, Dec 20, 2023 at 01:27:51PM +0800, Changbin Du wrote:
> > On Tue, Dec 19, 2023 at 01:52:03PM -0800, Luis Chamberlain wrote:
> > > On Tue, Dec 19, 2023 at 12:51:51PM -0800, Andrew Morton wrote:
> > > > On Tue, 19 Dec 2023 22:12:31 +0800 Changbin Du  
> > > > wrote:
> > > > 
> > > > > The commit 1a7b7d922081 ("modules: Use vmalloc special flag") moves
> > > > > do_free_init() into a global workqueue instead of call_rcu(). So now
> > > > > we should wait it via flush_work().
> > > > 
> > > > What are the runtime effects of this change?
> > > 
> > > Indeed that's needed given how old this culprit commit is:
> > > 
> > > git describe --contains 1a7b7d922081
> > > v5.2-rc1~192^2~5
> > > 
> > > Who did this work and for what reason? What triggered this itch?
> > >
> > Seems the waiting was introduced by commit ae646f0b9ca ("init: fix false 
> > positives
> > in W+X checking").
> > 
> > As what I have observed, mark_readonly() is only invoked by the first user 
> > mode
> > thread function kernel_init(), which is before userspace /init. So is it 
> > real
> > possible we have loaded modules at this point?
> 
> Are you saying we don't free any module inits at all then? I asked a lot
> of questions and your answers seem slim.
>
Yes, indeed no module loaded at all before mark_readonly(), at least on my 
desktop.
So I think we can just delete this synchronization. I am not sure whether there 
are
any historical reasons.

> How did you find this?
> What actual impact does this have without the patch?
>
This is a coincidence. We encountered a rcu problem which the barrier takes much
longger time to wait (this is an another story). So we reviewed the code and
found this issue.

There is no funcional problem without the patch. It's a unnecessary wait AFAIK,
and it does take a little cycles to wait the rcb callbacks.

> The commit must document this.
> 
>   Luis

-- 
Cheers,
Changbin Du



Re: [PATCH] modules: wait do_free_init correctly

2023-12-19 Thread Changbin Du
On Tue, Dec 19, 2023 at 01:52:03PM -0800, Luis Chamberlain wrote:
> On Tue, Dec 19, 2023 at 12:51:51PM -0800, Andrew Morton wrote:
> > On Tue, 19 Dec 2023 22:12:31 +0800 Changbin Du  
> > wrote:
> > 
> > > The commit 1a7b7d922081 ("modules: Use vmalloc special flag") moves
> > > do_free_init() into a global workqueue instead of call_rcu(). So now
> > > we should wait it via flush_work().
> > 
> > What are the runtime effects of this change?
> 
> Indeed that's needed given how old this culprit commit is:
> 
> git describe --contains 1a7b7d922081
> v5.2-rc1~192^2~5
> 
> Who did this work and for what reason? What triggered this itch?
>
Seems the waiting was introduced by commit ae646f0b9ca ("init: fix false 
positives
in W+X checking").

As what I have observed, mark_readonly() is only invoked by the first user mode
thread function kernel_init(), which is before userspace /init. So is it real
possible we have loaded modules at this point?

Cc Jeffrey Hugo 
> Is it perhaps for an out of tree driver that did something funky
> on its module exit?
> 
> As per Documentation/RCU/rcubarrier.rst rcu_barrier will ensure the
> callbacks complete, so interms of determinism both mechanisms will
> have waited for the free. It seems we're now just limiting the scope.
> 
> This could also mean initialization grew used to having RCU calls on
> init complete at this point in time, even for modules, and so localizing
> this wait may now also introduce other unexpected behaviour.
> 
>   Luis

-- 
Cheers,
Changbin Du



[PATCH] modules: wait do_free_init correctly

2023-12-19 Thread Changbin Du
The commit 1a7b7d922081 ("modules: Use vmalloc special flag") moves
do_free_init() into a global workqueue instead of call_rcu(). So now
we should wait it via flush_work().

Fixes: 1a7b7d922081 ("modules: Use vmalloc special flag")
Signed-off-by: Changbin Du 
Cc: Xiaoyi Su 
---
 include/linux/moduleloader.h | 2 ++
 init/main.c  | 5 +++--
 kernel/module/main.c | 5 +
 3 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/include/linux/moduleloader.h b/include/linux/moduleloader.h
index 001b2ce83832..f3d445d8ccd0 100644
--- a/include/linux/moduleloader.h
+++ b/include/linux/moduleloader.h
@@ -115,6 +115,8 @@ int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
struct module *mod);
 
+void flush_module_init_free_work(void);
+
 /* Any cleanup needed when module leaves. */
 void module_arch_cleanup(struct module *mod);
 
diff --git a/init/main.c b/init/main.c
index e24b0780fdff..f0b7e21ac67f 100644
--- a/init/main.c
+++ b/init/main.c
@@ -99,6 +99,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -1402,11 +1403,11 @@ static void mark_readonly(void)
if (rodata_enabled) {
/*
 * load_module() results in W+X mappings, which are cleaned
-* up with call_rcu().  Let's make sure that queued work is
+* up with init_free_wq. Let's make sure that queued work is
 * flushed so that we don't hit false positives looking for
 * insecure pages which are W+X.
 */
-   rcu_barrier();
+   flush_module_init_free_work();
mark_rodata_ro();
rodata_test();
} else
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 98fedfdb8db5..1943ccb7414f 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -2486,6 +2486,11 @@ static void do_free_init(struct work_struct *w)
}
 }
 
+void flush_module_init_free_work(void)
+{
+   flush_work(&init_free_wq);
+}
+
 #undef MODULE_PARAM_PREFIX
 #define MODULE_PARAM_PREFIX "module."
 /* Default value for module->async_probe_requested */
-- 
2.25.1




[PATCH] riscv: patch: remove lockdep assertion on lock text_mutex

2021-04-16 Thread Changbin Du
The function patch_insn_write() expects that the text_mutex is already
held. There's a case that text_mutex is acquired by ftrace_run_update_code()
under syscall context but then patch_insn_write() will be executed under the
migration kthread context as we involves stop machine. So we should remove
the assertion, or it can cause warning storm in kernel message.

[  104.641978] [ cut here ]
[  104.642327] WARNING: CPU: 0 PID: 13 at arch/riscv/kernel/patch.c:63 
patch_insn_write+0x166/0x17c
[  104.643587] Modules linked in:
[  104.644691] CPU: 0 PID: 13 Comm: migration/0 Not tainted 
5.12.0-rc7-00067-g9cdbf6467424 #102
[  104.644907] Hardware name: riscv-virtio,qemu (DT)
[  104.645068] Stopper: multi_cpu_stop+0x0/0x17e <- 0x0
[  104.645349] epc : patch_insn_write+0x166/0x17c
[  104.645467]  ra : patch_insn_write+0x162/0x17c
[  104.645534] epc : ffe059c6 ra : ffe059c2 sp : 
ffe002a33c70
[  104.645580]  gp : ffe0019e5518 tp : ffe002a232c0 t0 : 
ffe01295e8a8
[  104.645622]  t1 : 0001 t2 :  s0 : 
ffe002a33cc0
[  104.645675]  s1 : ffe07f72 a0 :  a1 : 

[  104.645716]  a2 : 0001 a3 :  a4 : 
0001
[  104.645757]  a5 : ffe0799e45c8 a6 : 000ca097 a7 : 

[  104.645798]  s2 : 0008 s3 : 0f72 s4 : 
ffe002a33ce0
[  104.645839]  s5 : 0f7a s6 : 0003 s7 : 
0003
[  104.645880]  s8 : 0004 s9 : 0002 s10: 

[  104.645920]  s11: 0002 t3 : 0001 t4 : 
ffe000c615c8
[  104.645958]  t5 : 7fff t6 : 0380
[  104.645998] status: 0100 badaddr:  cause: 
0003
[  104.646081] Call Trace:
[  104.646147] [] patch_insn_write+0x166/0x17c
[  104.646280] [] patch_text_nosync+0x10/0x32
[  104.646317] [] ftrace_update_ftrace_func+0x74/0xac
[  104.646352] [] ftrace_modify_all_code+0x9c/0x144
[  104.646387] [] __ftrace_modify_code+0x12/0x1c
[  104.646420] [] multi_cpu_stop+0xa8/0x17e
[  104.646451] [] cpu_stopper_thread+0xb2/0x156
[  104.646489] [] smpboot_thread_fn+0x102/0x1ea
[  104.646524] [] kthread+0x132/0x148
[  104.646556] [] ret_from_exception+0x0/0x14
[  104.646657] ---[ end trace ccf71babb9de4d5b ]---
[  104.647444] [ cut here ]

Signed-off-by: Changbin Du 
---
 arch/riscv/kernel/patch.c | 13 ++---
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/arch/riscv/kernel/patch.c b/arch/riscv/kernel/patch.c
index 0b552873a577..6d2ed9c15065 100644
--- a/arch/riscv/kernel/patch.c
+++ b/arch/riscv/kernel/patch.c
@@ -49,19 +49,18 @@ static void patch_unmap(int fixmap)
 }
 NOKPROBE_SYMBOL(patch_unmap);
 
+
+/*
+ * Before reaching here, it was expected to lock the text_mutex
+ * already, so we don't need to give another lock here and could
+ * ensure that it was safe between each cores.
+ */
 static int patch_insn_write(void *addr, const void *insn, size_t len)
 {
void *waddr = addr;
bool across_pages = (((uintptr_t) addr & ~PAGE_MASK) + len) > PAGE_SIZE;
int ret;
 
-   /*
-* Before reaching here, it was expected to lock the text_mutex
-* already, so we don't need to give another lock here and could
-* ensure that it was safe between each cores.
-*/
-   lockdep_assert_held(&text_mutex);
-
if (across_pages)
patch_map(addr + len, FIX_TEXT_POKE1);
 
-- 
2.27.0



Re: [PATCH] of/fdt: Check dtb pointer first in unflatten_device_tree

2021-03-25 Thread Changbin Du
On Wed, Mar 24, 2021 at 10:52:30AM -0600, Rob Herring wrote:
> On Wed, Mar 24, 2021 at 9:04 AM Changbin Du  wrote:
> >
> > The setup_arch() would invoke unflatten_device_tree() even no
> > valid fdt found. So we'd better check it first and return early.
> >
> > Signed-off-by: Changbin Du 
> > ---
> >  drivers/of/fdt.c | 5 +
> >  1 file changed, 5 insertions(+)
> >
> > diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
> > index dcc1dd96911a..05d439d63bc5 100644
> > --- a/drivers/of/fdt.c
> > +++ b/drivers/of/fdt.c
> > @@ -1225,6 +1225,11 @@ bool __init early_init_dt_scan(void *params)
> >   */
> >  void __init unflatten_device_tree(void)
> >  {
> > +   if (!initial_boot_params) {
> > +   pr_warn("No valid device tree found, continuing without\n");
> 
> How are you going to see this message if you have no DT?
>
This aligns to what unflatten_and_copy_device_tree() does.
 
> > +   return;
> 
> And the arch is supposed to just continue on oblivious that it has no DT?
>
As checking the arch code(arm, riscv), I suppose so.

> > +   }
> > +
> > __unflatten_device_tree(initial_boot_params, NULL, &of_root,
> > early_init_dt_alloc_memory_arch, false);
> 
> Soon as you get here with a NULL initial_boot_params, you'll get a
> backtrace and halt.
> 
No, we have returned before.

> >
> > --
> > 2.30.2
> >

-- 
Cheers,
Changbin Du


Re: [PATCH] riscv: Do not invoke early_init_dt_verify() twice

2021-03-25 Thread Changbin Du
On Wed, Mar 24, 2021 at 08:51:06PM +0530, Anup Patel wrote:
> On Wed, Mar 24, 2021 at 8:33 PM Changbin Du  wrote:
> >
> > In the setup_arch() of riscv, function early_init_dt_verify() has
> > been done by parse_dtb(). So no need to call it again. Just directly
> > invoke unflatten_device_tree().
> >
> > Signed-off-by: Changbin Du 
> > ---
> >  arch/riscv/kernel/setup.c | 5 +
> >  1 file changed, 1 insertion(+), 4 deletions(-)
> >
> > diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
> > index f8f15332caa2..2a3d487e1710 100644
> > --- a/arch/riscv/kernel/setup.c
> > +++ b/arch/riscv/kernel/setup.c
> > @@ -255,10 +255,7 @@ void __init setup_arch(char **cmdline_p)
> >  #if IS_ENABLED(CONFIG_BUILTIN_DTB)
> > unflatten_and_copy_device_tree();
> >  #else
> > -   if (early_init_dt_verify(__va(dtb_early_pa)))
> > -   unflatten_device_tree();
> > -   else
> > -   pr_err("No DTB found in kernel mappings\n");
> > +   unflatten_device_tree();
> >  #endif
> 
> The early_init_dt_verify() set he DTB base address in Linux OF.
> 
> When parse_dtb() calls early_init_dt_verify(), MMU is enabled but
> we have temporary mapping for DTB (i.e. dtb_early_va).
> 
> After paging_init(), we have moved to final swapper_pg_dir so
> temporary mapping for DTB does not exists anymore but DTB
> is at same physical address so update DTB base address in
> Linux OF by calling early_init_dt_verify() again.
> 
> Based on above, NACK to this patch.
>
No problem, thanks!
 
> Regards,
> Anup
> 
> > misc_mem_init();
> >
> > --
> > 2.30.2
> >
> >
> > ___
> > linux-riscv mailing list
> > linux-ri...@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-riscv

-- 
Cheers,
Changbin Du


[PATCH] of/fdt: Check dtb pointer first in unflatten_device_tree

2021-03-24 Thread Changbin Du
The setup_arch() would invoke unflatten_device_tree() even no
valid fdt found. So we'd better check it first and return early.

Signed-off-by: Changbin Du 
---
 drivers/of/fdt.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index dcc1dd96911a..05d439d63bc5 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -1225,6 +1225,11 @@ bool __init early_init_dt_scan(void *params)
  */
 void __init unflatten_device_tree(void)
 {
+   if (!initial_boot_params) {
+   pr_warn("No valid device tree found, continuing without\n");
+   return;
+   }
+
__unflatten_device_tree(initial_boot_params, NULL, &of_root,
early_init_dt_alloc_memory_arch, false);
 
-- 
2.30.2



[PATCH] riscv: Do not invoke early_init_dt_verify() twice

2021-03-24 Thread Changbin Du
In the setup_arch() of riscv, function early_init_dt_verify() has
been done by parse_dtb(). So no need to call it again. Just directly
invoke unflatten_device_tree().

Signed-off-by: Changbin Du 
---
 arch/riscv/kernel/setup.c | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
index f8f15332caa2..2a3d487e1710 100644
--- a/arch/riscv/kernel/setup.c
+++ b/arch/riscv/kernel/setup.c
@@ -255,10 +255,7 @@ void __init setup_arch(char **cmdline_p)
 #if IS_ENABLED(CONFIG_BUILTIN_DTB)
unflatten_and_copy_device_tree();
 #else
-   if (early_init_dt_verify(__va(dtb_early_pa)))
-   unflatten_device_tree();
-   else
-   pr_err("No DTB found in kernel mappings\n");
+   unflatten_device_tree();
 #endif
misc_mem_init();
 
-- 
2.30.2



[PATCH] efi/fdt: fix panic when no valid fdt found

2021-03-24 Thread Changbin Du
setup_arch() would invoke efi_init()->efi_get_fdt_params(). If no
valid fdt found then initial_boot_params will be null. So we
should stop further fdt processing here. I encountered this
issue on risc-v.

Signed-off-by: Changbin Du 
---
 drivers/firmware/efi/fdtparams.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/firmware/efi/fdtparams.c b/drivers/firmware/efi/fdtparams.c
index bb042ab7c2be..e901f8564ca0 100644
--- a/drivers/firmware/efi/fdtparams.c
+++ b/drivers/firmware/efi/fdtparams.c
@@ -98,6 +98,9 @@ u64 __init efi_get_fdt_params(struct efi_memory_map_data *mm)
BUILD_BUG_ON(ARRAY_SIZE(target) != ARRAY_SIZE(name));
BUILD_BUG_ON(ARRAY_SIZE(target) != ARRAY_SIZE(dt_params[0].params));
 
+   if (!fdt)
+   return 0;
+
for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
node = fdt_path_offset(fdt, dt_params[i].path);
if (node < 0)
-- 
2.30.2



Re: [RESEND PATCH v2] perf stat: improve readability of shadow stats

2021-03-18 Thread Changbin Du
On Tue, Mar 16, 2021 at 02:53:41PM +0100, Jiri Olsa wrote:
> On Mon, Mar 15, 2021 at 10:30:47PM +0800, Changbin Du wrote:
> 
> SNIP
> 
> > diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
> > index 6ccf21a72f06..3f800e71126f 100644
> > --- a/tools/perf/util/stat-shadow.c
> > +++ b/tools/perf/util/stat-shadow.c
> > @@ -9,6 +9,7 @@
> >  #include "expr.h"
> >  #include "metricgroup.h"
> >  #include "cgroup.h"
> > +#include "units.h"
> >  #include 
> >  
> >  /*
> > @@ -1270,18 +1271,15 @@ void perf_stat__print_shadow_stats(struct 
> > perf_stat_config *config,
> > generic_metric(config, evsel->metric_expr, 
> > evsel->metric_events, NULL,
> > evsel->name, evsel->metric_name, NULL, 1, cpu, 
> > out, st);
> > } else if (runtime_stat_n(st, STAT_NSECS, cpu, &rsd) != 0) {
> > -   char unit = 'M';
> > -   char unit_buf[10];
> > +   char unit = ' ';
> > +   char unit_buf[10] = "/sec";
> >  
> > total = runtime_stat_avg(st, STAT_NSECS, cpu, &rsd);
> > -
> > if (total)
> > -   ratio = 1000.0 * avg / total;
> > -   if (ratio < 0.001) {
> > -   ratio *= 1000;
> > -   unit = 'K';
> > -   }
> > -   snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit);
> > +   ratio = convert_unit_double(10.0 * avg / total, 
> > &unit);
> > +
> > +   if (unit != ' ')
> > +   snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit);
> > print_metric(config, ctxp, NULL, "%8.3f", unit_buf, ratio);
> 
> hum, does this still change the metric unit in the csv output? 'perf -a -x,'
>
The unit is changed in csv format, too. See below.

before:
$ sudo ./perf stat -a -x, -- sleep 1
8037.85,msec,cpu-clock,8037851596,100.00,7.999,CPUs utilized
714,,context-switches,8037838466,100.00,0.089,K/sec
11,,cpu-migrations,8037832590,100.00,0.001,K/sec
71,,page-faults,8037824974,100.00,0.009,K/sec
84033551,,cycles,8037750471,100.00,0.010,GHz
22563553,,instructions,8037733879,100.00,0.27,insn per cycle
4685736,,branches,8037708301,100.00,0.583,M/sec
356327,,branch-misses,8037667950,100.00,7.60,of all branches

after:
$ sudo ./perf stat -a -x, -- sleep 1
8026.19,msec,cpu-clock,8026194365,100.00,7.983,CPUs utilized
621,,context-switches,8026178186,100.00,77.372,/sec
16,,cpu-migrations,8026172135,100.00,1.993,/sec
73,,page-faults,8026142626,100.00,9.095,/sec
92645028,,cycles,8026066285,100.00,0.012,GHz
56268285,,instructions,8026048894,100.00,0.61,insn per cycle
10979859,,branches,8026022127,100.00,1.368,M/sec
441719,,branch-misses,8025981169,100.00,4.02,of all branches

But is this a real problem?

> jirka
> 
> > } else if (perf_stat_evsel__is(evsel, SMI_NUM)) {
> > print_smi_cost(config, cpu, out, st, &rsd);
> > diff --git a/tools/perf/util/units.c b/tools/perf/util/units.c
> > index a46762aec4c9..32c39cfe209b 100644
> > --- a/tools/perf/util/units.c
> > +++ b/tools/perf/util/units.c
> 
> SNIP
> 

-- 
Cheers,
Changbin Du


[RESEND PATCH v2] perf stat: improve readability of shadow stats

2021-03-15 Thread Changbin Du
This adds function convert_unit_double() and selects appropriate
unit for shadow stats between K/M/G.

$ sudo ./perf stat -a -- sleep 1

Before: Unit 'M' is selected even the number is very small.
 Performance counter stats for 'system wide':

  4,003.06 msec cpu-clock #3.998 CPUs utilized
16,179  context-switches  #0.004 M/sec
   161  cpu-migrations#0.040 K/sec
 4,699  page-faults   #0.001 M/sec
 6,135,801,925  cycles#1.533 GHz
  (83.21%)
 5,783,308,491  stalled-cycles-frontend   #   94.26% frontend cycles 
idle (83.21%)
 4,543,694,050  stalled-cycles-backend#   74.05% backend cycles 
idle  (66.49%)
 4,720,130,587  instructions  #0.77  insn per cycle
  #1.23  stalled cycles per 
insn  (83.28%)
   753,848,078  branches  #  188.318 M/sec  
  (83.61%)
37,457,747  branch-misses #4.97% of all branches
  (83.48%)

   1.001283725 seconds time elapsed

After:
$ sudo ./perf stat -a -- sleep 2

 Performance counter stats for 'system wide':

  8,005.52 msec cpu-clock #3.999 CPUs utilized
10,715  context-switches  #1.338 K/sec
   785  cpu-migrations#   98.057 /sec
   102  page-faults   #   12.741 /sec
 1,948,202,279  cycles#0.243 GHz
 2,816,470,932  stalled-cycles-frontend   #  144.57% frontend cycles 
idle
 2,661,172,207  stalled-cycles-backend#  136.60% backend cycles idle
   464,172,105  instructions  #0.24  insn per cycle
  #6.07  stalled cycles per 
insn
91,567,662  branches  #   11.438 M/sec
 7,756,054  branch-misses #8.47% of all branches

   2.002040043 seconds time elapsed

Signed-off-by: Changbin Du 

v2:
  o do not change 'sec' to 'cpu-sec'.
  o use convert_unit_double to implement convert_unit.
---
 tools/perf/util/stat-shadow.c | 16 +++-
 tools/perf/util/units.c   | 21 ++---
 tools/perf/util/units.h   |  1 +
 3 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 6ccf21a72f06..3f800e71126f 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -9,6 +9,7 @@
 #include "expr.h"
 #include "metricgroup.h"
 #include "cgroup.h"
+#include "units.h"
 #include 
 
 /*
@@ -1270,18 +1271,15 @@ void perf_stat__print_shadow_stats(struct 
perf_stat_config *config,
generic_metric(config, evsel->metric_expr, 
evsel->metric_events, NULL,
evsel->name, evsel->metric_name, NULL, 1, cpu, 
out, st);
} else if (runtime_stat_n(st, STAT_NSECS, cpu, &rsd) != 0) {
-   char unit = 'M';
-   char unit_buf[10];
+   char unit = ' ';
+   char unit_buf[10] = "/sec";
 
total = runtime_stat_avg(st, STAT_NSECS, cpu, &rsd);
-
if (total)
-   ratio = 1000.0 * avg / total;
-   if (ratio < 0.001) {
-   ratio *= 1000;
-   unit = 'K';
-   }
-   snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit);
+   ratio = convert_unit_double(10.0 * avg / total, 
&unit);
+
+   if (unit != ' ')
+   snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit);
print_metric(config, ctxp, NULL, "%8.3f", unit_buf, ratio);
} else if (perf_stat_evsel__is(evsel, SMI_NUM)) {
print_smi_cost(config, cpu, out, st, &rsd);
diff --git a/tools/perf/util/units.c b/tools/perf/util/units.c
index a46762aec4c9..32c39cfe209b 100644
--- a/tools/perf/util/units.c
+++ b/tools/perf/util/units.c
@@ -33,28 +33,35 @@ unsigned long parse_tag_value(const char *str, struct 
parse_tag *tags)
return (unsigned long) -1;
 }
 
-unsigned long convert_unit(unsigned long value, char *unit)
+double convert_unit_double(double value, char *unit)
 {
*unit = ' ';
 
-   if (value > 1000) {
-   value /= 1000;
+   if (value > 1000.0) {
+   value /= 1000.0;
*unit = 'K';
}
 
-   if (value > 1000) {
-   value /= 1000;
+   if (value > 1000.0) {
+   value /= 1000.0;

[PATCH v2] perf stat: improve readability of shadow stats

2021-03-04 Thread Changbin Du
This adds function convert_unit_double() and selects appropriate
unit for shadow stats between K/M/G.

$ sudo ./perf stat -a -- sleep 1

Before: Unit 'M' is selected even the number is very small.
 Performance counter stats for 'system wide':

  4,003.06 msec cpu-clock #3.998 CPUs utilized
16,179  context-switches  #0.004 M/sec
   161  cpu-migrations#0.040 K/sec
 4,699  page-faults   #0.001 M/sec
 6,135,801,925  cycles#1.533 GHz
  (83.21%)
 5,783,308,491  stalled-cycles-frontend   #   94.26% frontend cycles 
idle (83.21%)
 4,543,694,050  stalled-cycles-backend#   74.05% backend cycles 
idle  (66.49%)
 4,720,130,587  instructions  #0.77  insn per cycle
  #1.23  stalled cycles per 
insn  (83.28%)
   753,848,078  branches  #  188.318 M/sec  
  (83.61%)
37,457,747  branch-misses #4.97% of all branches
  (83.48%)

   1.001283725 seconds time elapsed

After:
$ sudo ./perf stat -a -- sleep 2

 Performance counter stats for 'system wide':

  8,005.52 msec cpu-clock #3.999 CPUs utilized
10,715  context-switches  #1.338 K/sec
   785  cpu-migrations#   98.057 /sec
   102  page-faults   #   12.741 /sec
 1,948,202,279  cycles#0.243 GHz
 2,816,470,932  stalled-cycles-frontend   #  144.57% frontend cycles 
idle
 2,661,172,207  stalled-cycles-backend#  136.60% backend cycles idle
   464,172,105  instructions  #0.24  insn per cycle
  #6.07  stalled cycles per 
insn
91,567,662  branches  #   11.438 M/sec
 7,756,054  branch-misses #8.47% of all branches

   2.002040043 seconds time elapsed

Signed-off-by: Changbin Du 

v2:
  o do not change 'sec' to 'cpu-sec'.
  o use convert_unit_double to implement convert_unit.
---
 tools/perf/util/stat-shadow.c | 16 +++-
 tools/perf/util/units.c   | 21 ++---
 tools/perf/util/units.h   |  1 +
 3 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 6ccf21a72f06..3f800e71126f 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -9,6 +9,7 @@
 #include "expr.h"
 #include "metricgroup.h"
 #include "cgroup.h"
+#include "units.h"
 #include 
 
 /*
@@ -1270,18 +1271,15 @@ void perf_stat__print_shadow_stats(struct 
perf_stat_config *config,
generic_metric(config, evsel->metric_expr, 
evsel->metric_events, NULL,
evsel->name, evsel->metric_name, NULL, 1, cpu, 
out, st);
} else if (runtime_stat_n(st, STAT_NSECS, cpu, &rsd) != 0) {
-   char unit = 'M';
-   char unit_buf[10];
+   char unit = ' ';
+   char unit_buf[10] = "/sec";
 
total = runtime_stat_avg(st, STAT_NSECS, cpu, &rsd);
-
if (total)
-   ratio = 1000.0 * avg / total;
-   if (ratio < 0.001) {
-   ratio *= 1000;
-   unit = 'K';
-   }
-   snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit);
+   ratio = convert_unit_double(10.0 * avg / total, 
&unit);
+
+   if (unit != ' ')
+   snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit);
print_metric(config, ctxp, NULL, "%8.3f", unit_buf, ratio);
} else if (perf_stat_evsel__is(evsel, SMI_NUM)) {
print_smi_cost(config, cpu, out, st, &rsd);
diff --git a/tools/perf/util/units.c b/tools/perf/util/units.c
index a46762aec4c9..32c39cfe209b 100644
--- a/tools/perf/util/units.c
+++ b/tools/perf/util/units.c
@@ -33,28 +33,35 @@ unsigned long parse_tag_value(const char *str, struct 
parse_tag *tags)
return (unsigned long) -1;
 }
 
-unsigned long convert_unit(unsigned long value, char *unit)
+double convert_unit_double(double value, char *unit)
 {
*unit = ' ';
 
-   if (value > 1000) {
-   value /= 1000;
+   if (value > 1000.0) {
+   value /= 1000.0;
*unit = 'K';
}
 
-   if (value > 1000) {
-   value /= 1000;
+   if (value > 1000.0) {
+   value /= 1000.0;

Re: [PATCH] perf stat: improve readability of shadow stats

2021-03-04 Thread Changbin Du
On Tue, Mar 02, 2021 at 09:25:24AM -0300, Arnaldo Carvalho de Melo wrote:
> Em Tue, Mar 02, 2021 at 11:08:40AM +0900, Namhyung Kim escreveu:
> > On Tue, Mar 2, 2021 at 4:19 AM Jiri Olsa  wrote:
> > >
> > > On Tue, Mar 02, 2021 at 01:24:02AM +0800, Changbin Du wrote:
> > > > This does follow two changes:
> > > >   1) Select appropriate unit between K/M/G.
> > > >   2) Use 'cpu-sec' instead of 'sec' to state this is not the wall-time.
> > > >
> > > > $ sudo ./perf stat -a -- sleep 1
> > > >
> > > > Before: Unit 'M' is selected even the number is very small.
> > > >  Performance counter stats for 'system wide':
> > > >
> > > >   4,003.06 msec cpu-clock #3.998 CPUs 
> > > > utilized
> > > > 16,179  context-switches  #0.004 M/sec
> > > >161  cpu-migrations#0.040 K/sec
> > > >  4,699  page-faults   #0.001 M/sec
> > > >  6,135,801,925  cycles#1.533 GHz
> > > >   (83.21%)
> > > >  5,783,308,491  stalled-cycles-frontend   #   94.26% frontend 
> > > > cycles idle (83.21%)
> > > >  4,543,694,050  stalled-cycles-backend#   74.05% backend 
> > > > cycles idle  (66.49%)
> > > >  4,720,130,587  instructions  #0.77  insn per 
> > > > cycle
> > > >   #1.23  stalled 
> > > > cycles per insn  (83.28%)
> > > >753,848,078  branches  #  188.318 M/sec  
> > > >   (83.61%)
> > > > 37,457,747  branch-misses #4.97% of all 
> > > > branches  (83.48%)
> > > >
> > > >1.001283725 seconds time elapsed
> > > >
> > > > After:
> > > > $ sudo ./perf stat -a -- sleep 2
> > > >
> > > >  Performance counter stats for 'system wide':
> > > >
> > > >   8,003.20 msec cpu-clock #3.998 CPUs 
> > > > utilized
> > > >  9,768  context-switches  #1.221 K/cpu-sec
> > > >164  cpu-migrations#   20.492  /cpu-sec
> > >
> > > should you remove also the leading '/' in ' /cpu-sec' ?
> > 
> > The change looks good.  And I think we should keep '/' otherwise it'd be
> > more confusing.
> 
> Perhaps:
> 
>8,003.20 msec cpu-clock #3.998 CPUs utilized
>   9,768  context-switches  #1.221 K/cpu-sec
> 164  cpu-migrations#   20.492 /cpu-sec
> 
> ?
>
sure. Now it is:
$ sudo ./perf stat 
[sudo] password for changbin: 
^C
 Performance counter stats for 'system wide':

  6,046.61 msec cpu-clock #3.999 CPUs utilized  

 7,569  context-switches  #1.252 K/sec  

   587  cpu-migrations#   97.079 /sec   

   229  page-faults   #   37.872 /sec   

 1,484,855,385  cycles#0.246 GHz

 2,112,863,483  stalled-cycles-frontend   #  142.29% frontend cycles 
idle   
 1,980,746,623  stalled-cycles-backend#  133.40% backend cycles 
idle
   454,477,035  instructions  #0.31  insn per cycle 

  #4.65  stalled cycles per 
insn
89,992,521  branches  #   14.883 M/sec  

 6,196,599  branch-misses #6.89% of all branches


   1.512029866 seconds time elapsed

 
> - Arnaldo
>  
> > >
> > >
> > > SNIP
> > >
> > > > @@ -1270,18 +1271,14 @@ void perf_stat__print_shadow_stats(struct 
> > > > perf_stat_config *config,
> > > >   generic_metric(config, evsel->metric_expr, 
> > > > evsel->metric_events, NULL,
> > > >   evsel->name, evsel->metric_name, NULL, 1, 
> > > > cpu, out, st);
> > > >   } else if (runtime_stat_n(st, STAT_NSECS, cpu, &rsd) != 0) {
> > > > - char unit = 'M';
> > > &g

Re: [PATCH] perf stat: improve readability of shadow stats

2021-03-04 Thread Changbin Du
On Mon, Mar 01, 2021 at 08:19:20PM +0100, Jiri Olsa wrote:
> On Tue, Mar 02, 2021 at 01:24:02AM +0800, Changbin Du wrote:
> > This does follow two changes:
> >   1) Select appropriate unit between K/M/G.
> >   2) Use 'cpu-sec' instead of 'sec' to state this is not the wall-time.
> > 
> > $ sudo ./perf stat -a -- sleep 1
> > 
> > Before: Unit 'M' is selected even the number is very small.
> >  Performance counter stats for 'system wide':
> > 
> >   4,003.06 msec cpu-clock #3.998 CPUs utilized
> > 16,179  context-switches  #0.004 M/sec
> >161  cpu-migrations#0.040 K/sec
> >  4,699  page-faults   #0.001 M/sec
> >  6,135,801,925  cycles#1.533 GHz
> >   (83.21%)
> >  5,783,308,491  stalled-cycles-frontend   #   94.26% frontend 
> > cycles idle (83.21%)
> >  4,543,694,050  stalled-cycles-backend#   74.05% backend cycles 
> > idle  (66.49%)
> >  4,720,130,587  instructions  #0.77  insn per cycle
> >   #1.23  stalled cycles 
> > per insn  (83.28%)
> >753,848,078  branches  #  188.318 M/sec  
> >   (83.61%)
> > 37,457,747  branch-misses #4.97% of all 
> > branches  (83.48%)
> > 
> >1.001283725 seconds time elapsed
> > 
> > After:
> > $ sudo ./perf stat -a -- sleep 2
> > 
> >  Performance counter stats for 'system wide':
> > 
> >   8,003.20 msec cpu-clock #3.998 CPUs utilized
> >  9,768  context-switches  #1.221 K/cpu-sec
> >164  cpu-migrations#   20.492  /cpu-sec
> 
> should you remove also the leading '/' in ' /cpu-sec' ?
> 
> 
> SNIP
> 
> > @@ -1270,18 +1271,14 @@ void perf_stat__print_shadow_stats(struct 
> > perf_stat_config *config,
> > generic_metric(config, evsel->metric_expr, 
> > evsel->metric_events, NULL,
> > evsel->name, evsel->metric_name, NULL, 1, cpu, 
> > out, st);
> > } else if (runtime_stat_n(st, STAT_NSECS, cpu, &rsd) != 0) {
> > -   char unit = 'M';
> > +   char unit = ' ';
> > char unit_buf[10];
> >  
> > total = runtime_stat_avg(st, STAT_NSECS, cpu, &rsd);
> > -
> > if (total)
> > -   ratio = 1000.0 * avg / total;
> > -   if (ratio < 0.001) {
> > -   ratio *= 1000;
> > -   unit = 'K';
> > -       }
> > -   snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit);
> > +   ratio = convert_unit_double(10.0 * avg / total, 
> > &unit);
> > +
> > +   snprintf(unit_buf, sizeof(unit_buf), "%c/cpu-sec", unit);
> > print_metric(config, ctxp, NULL, "%8.3f", unit_buf, ratio);
> 
> hum this will change -x output that people parse, so I don't think we can do 
> that
okay, so skip this change and keep another.

-- 
Cheers,
Changbin Du


[PATCH] perf stat: improve readability of shadow stats

2021-03-01 Thread Changbin Du
This does follow two changes:
  1) Select appropriate unit between K/M/G.
  2) Use 'cpu-sec' instead of 'sec' to state this is not the wall-time.

$ sudo ./perf stat -a -- sleep 1

Before: Unit 'M' is selected even the number is very small.
 Performance counter stats for 'system wide':

  4,003.06 msec cpu-clock #3.998 CPUs utilized
16,179  context-switches  #0.004 M/sec
   161  cpu-migrations#0.040 K/sec
 4,699  page-faults   #0.001 M/sec
 6,135,801,925  cycles#1.533 GHz
  (83.21%)
 5,783,308,491  stalled-cycles-frontend   #   94.26% frontend cycles 
idle (83.21%)
 4,543,694,050  stalled-cycles-backend#   74.05% backend cycles 
idle  (66.49%)
 4,720,130,587  instructions  #0.77  insn per cycle
  #1.23  stalled cycles per 
insn  (83.28%)
   753,848,078  branches  #  188.318 M/sec  
  (83.61%)
37,457,747  branch-misses #4.97% of all branches
  (83.48%)

   1.001283725 seconds time elapsed

After:
$ sudo ./perf stat -a -- sleep 2

 Performance counter stats for 'system wide':

  8,003.20 msec cpu-clock #3.998 CPUs utilized
 9,768  context-switches  #1.221 K/cpu-sec
   164  cpu-migrations#   20.492  /cpu-sec
74,146  page-faults   #9.265 K/cpu-sec
19,008,796,806  cycles#2.375 GHz
  (83.21%)
14,789,443,853  stalled-cycles-frontend   #   77.80% frontend cycles 
idle (83.29%)
11,867,812,064  stalled-cycles-backend#   62.43% backend cycles 
idle  (66.80%)
 9,898,252,603  instructions  #0.52  insn per cycle
  #1.49  stalled cycles per 
insn  (83.41%)
 2,063,251,998  branches  #  257.803 M/cpu-sec  
  (83.41%)
86,941,704  branch-misses #4.21% of all branches
  (83.30%)

   2.001743706 seconds time elapsed

Signed-off-by: Changbin Du 
---
 tools/perf/util/stat-shadow.c | 13 +
 tools/perf/util/units.c   | 22 ++
 tools/perf/util/units.h   |  1 +
 3 files changed, 28 insertions(+), 8 deletions(-)

diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 6ccf21a72f06..786b5ef512d8 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -9,6 +9,7 @@
 #include "expr.h"
 #include "metricgroup.h"
 #include "cgroup.h"
+#include "units.h"
 #include 
 
 /*
@@ -1270,18 +1271,14 @@ void perf_stat__print_shadow_stats(struct 
perf_stat_config *config,
generic_metric(config, evsel->metric_expr, 
evsel->metric_events, NULL,
evsel->name, evsel->metric_name, NULL, 1, cpu, 
out, st);
} else if (runtime_stat_n(st, STAT_NSECS, cpu, &rsd) != 0) {
-   char unit = 'M';
+   char unit = ' ';
char unit_buf[10];
 
total = runtime_stat_avg(st, STAT_NSECS, cpu, &rsd);
-
if (total)
-   ratio = 1000.0 * avg / total;
-   if (ratio < 0.001) {
-   ratio *= 1000;
-   unit = 'K';
-   }
-   snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit);
+   ratio = convert_unit_double(10.0 * avg / total, 
&unit);
+
+   snprintf(unit_buf, sizeof(unit_buf), "%c/cpu-sec", unit);
print_metric(config, ctxp, NULL, "%8.3f", unit_buf, ratio);
} else if (perf_stat_evsel__is(evsel, SMI_NUM)) {
print_smi_cost(config, cpu, out, st, &rsd);
diff --git a/tools/perf/util/units.c b/tools/perf/util/units.c
index a46762aec4c9..ac13b5ecde31 100644
--- a/tools/perf/util/units.c
+++ b/tools/perf/util/units.c
@@ -55,6 +55,28 @@ unsigned long convert_unit(unsigned long value, char *unit)
return value;
 }
 
+double convert_unit_double(double value, char *unit)
+{
+   *unit = ' ';
+
+   if (value > 1000.0) {
+   value /= 1000.0;
+   *unit = 'K';
+   }
+
+   if (value > 1000.0) {
+   value /= 1000.0;
+   *unit = 'M';
+   }
+
+   if (value > 1000.0) {
+   value /= 1000.0;
+   *unit = 'G';
+   }
+
+   return value;
+}
+
 int unit_number__scnprintf(char *buf, size_t size, u64 n)
 

[PATCH] riscv: uaccess: fix __put_kernel_nofault()

2020-11-01 Thread Changbin Du
The copy_from_kernel_nofault() is broken on riscv because the 'dst' and
'src' are mistakenly reversed in __put_kernel_nofault() macro.

copy_to_kernel_nofault:
...
0xffe0003159b8 <+30>:sd  a4,0(a1) # a1 aka 'src'

Fixes: d464118cdc ("riscv: implement __get_kernel_nofault and 
__put_user_nofault")
Signed-off-by: Changbin Du 
Cc: Christoph Hellwig 
---
 arch/riscv/include/asm/uaccess.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/riscv/include/asm/uaccess.h b/arch/riscv/include/asm/uaccess.h
index c47e6b35c551..824b2c9da75b 100644
--- a/arch/riscv/include/asm/uaccess.h
+++ b/arch/riscv/include/asm/uaccess.h
@@ -476,7 +476,7 @@ do {
\
 do {   \
long __kr_err;  \
\
-   __put_user_nocheck(*((type *)(dst)), (type *)(src), __kr_err);  \
+   __put_user_nocheck(*((type *)(src)), (type *)(dst), __kr_err);  \
if (unlikely(__kr_err)) \
goto err_label; \
 } while (0)
-- 
2.17.1




Re: [RESEND PATCH] perf: ftrace: Add filter support for option -F/--funcs

2020-09-05 Thread Changbin Du
On Fri, Sep 04, 2020 at 03:59:59PM -0300, Arnaldo Carvalho de Melo wrote:
> Em Fri, Sep 04, 2020 at 01:27:16PM -0300, Arnaldo Carvalho de Melo escreveu:
> > Em Fri, Sep 04, 2020 at 11:23:57PM +0800, Changbin Du escreveu:
> > > Same as 'perf probe -F', this patch adds filter support for the ftrace
> > > subcommand option '-F, --funcs <[FILTER]>'.
> > > 
> > > Here is an example that only lists functions which start with 'vfs_':
> > > $ sudo perf ftrace -F vfs_*
> > > vfs_fadvise
> > > vfs_fallocate
> > > vfs_truncate
> > > vfs_open
> > > vfs_setpos
> > > vfs_llseek
> > > vfs_readf
> > > vfs_writef
> > > ...
> > 
> > I'll process these now, the urgent ones were already sent to Linus, so I
> > will now concentrate on the new stuff for v5.10,
> > 
> > Thanks for working on this!
> 
> Thanks, applied, will go to v5.10, i.e. to my perf/core branch as soon
> as the usual set of tests pass,
> 
> - Arnaldo
Got it. Thank you!

-- 
Cheers,
Changbin Du


[RESEND PATCH] perf: ftrace: Add filter support for option -F/--funcs

2020-09-04 Thread Changbin Du
Same as 'perf probe -F', this patch adds filter support for the ftrace
subcommand option '-F, --funcs <[FILTER]>'.

Here is an example that only lists functions which start with 'vfs_':
$ sudo perf ftrace -F vfs_*
vfs_fadvise
vfs_fallocate
vfs_truncate
vfs_open
vfs_setpos
vfs_llseek
vfs_readf
vfs_writef
...

Suggested-by: Arnaldo Carvalho de Melo 
Signed-off-by: Changbin Du 
---
 tools/perf/Documentation/perf-ftrace.txt |  3 +-
 tools/perf/builtin-ftrace.c  | 84 ++--
 2 files changed, 80 insertions(+), 7 deletions(-)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 78358af9a1c4..1e91121bac0f 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -33,7 +33,8 @@ OPTIONS
 
 -F::
 --funcs::
-List all available functions to trace.
+List available functions to trace. It accepts a pattern to
+only list interested functions.
 
 -p::
 --pid=::
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 1d44bc2f63d8..9366fad591dc 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -25,6 +25,7 @@
 #include "target.h"
 #include "cpumap.h"
 #include "thread_map.h"
+#include "strfilter.h"
 #include "util/cap.h"
 #include "util/config.h"
 #include "util/units.h"
@@ -36,7 +37,6 @@ struct perf_ftrace {
struct evlist   *evlist;
struct target   target;
const char  *tracer;
-   boollist_avail_functions;
struct list_headfilters;
struct list_headnotrace;
struct list_headgraph_funcs;
@@ -181,6 +181,40 @@ static int read_tracing_file_to_stdout(const char *name)
return ret;
 }
 
+static int read_tracing_file_by_line(const char *name,
+void (*cb)(char *str, void *arg),
+void *cb_arg)
+{
+   char *line = NULL;
+   size_t len = 0;
+   char *file;
+   FILE *fp;
+
+   file = get_tracing_file(name);
+   if (!file) {
+   pr_debug("cannot get tracing file: %s\n", name);
+   return -1;
+   }
+
+   fp = fopen(file, "r");
+   if (fp == NULL) {
+   pr_debug("cannot open tracing file: %s\n", name);
+   put_tracing_file(file);
+   return -1;
+   }
+
+   while (getline(&line, &len, fp) != -1) {
+   cb(line, cb_arg);
+   }
+
+   if (line)
+   free(line);
+
+   fclose(fp);
+   put_tracing_file(file);
+   return 0;
+}
+
 static int write_tracing_file_int(const char *name, int value)
 {
char buf[16];
@@ -557,9 +591,6 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
signal(SIGCHLD, sig_handler);
signal(SIGPIPE, sig_handler);
 
-   if (ftrace->list_avail_functions)
-   return 
read_tracing_file_to_stdout("available_filter_functions");
-
if (reset_tracing_files(ftrace) < 0) {
pr_err("failed to reset ftrace\n");
goto out;
@@ -683,6 +714,46 @@ static int perf_ftrace_config(const char *var, const char 
*value, void *cb)
return -1;
 }
 
+static void list_function_cb(char *str, void *arg)
+{
+   struct strfilter *filter = (struct strfilter *)arg;
+
+   if (strfilter__compare(filter, str))
+   printf("%s", str);
+}
+
+static int opt_list_avail_functions(const struct option *opt __maybe_unused,
+   const char *str, int unset)
+{
+   struct strfilter *filter;
+   const char *err = NULL;
+   int ret;
+
+   if (unset || !str)
+   return -1;
+
+   filter = strfilter__new(str, &err);
+   if (!filter)
+   return err ? -EINVAL : -ENOMEM;
+
+   ret = strfilter__or(filter, str, &err);
+   if (ret == -EINVAL) {
+   pr_err("Filter parse error at %td.\n", err - str + 1);
+   pr_err("Source: \"%s\"\n", str);
+   pr_err(" %*c\n", (int)(err - str + 1), '^');
+   strfilter__delete(filter);
+   return ret;
+   }
+
+   ret = read_tracing_file_by_line("available_filter_functions",
+   list_function_cb, filter);
+   strfilter__delete(filter);
+   if (ret < 0)
+   return ret;
+
+   exit(0);
+}
+
 static int parse_filter_func(const struct option *opt, const char *str,
 int unset __maybe_unused)
 {
@@ -817,8 +888,9 @@ int cmd_ftrace(int argc, const char **argv)
const struct option ftr

[PATCH] kcsan: kconfig: Move to menu 'Generic Kernel Debugging Instruments'

2020-09-04 Thread Changbin Du
This moves the KCSAN kconfig items under menu 'Generic Kernel Debugging
Instruments' where UBSAN resides.

Signed-off-by: Changbin Du 
---
 lib/Kconfig.debug | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index e068c3c7189a..0c781f912f9f 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -520,8 +520,8 @@ config DEBUG_FS_ALLOW_NONE
 endchoice
 
 source "lib/Kconfig.kgdb"
-
 source "lib/Kconfig.ubsan"
+source "lib/Kconfig.kcsan"
 
 endmenu
 
@@ -1620,8 +1620,6 @@ config PROVIDE_OHCI1394_DMA_INIT
 
 source "samples/Kconfig"
 
-source "lib/Kconfig.kcsan"
-
 config ARCH_HAS_DEVMEM_IS_ALLOWED
bool
 
-- 
2.25.1



Re: localmodconfig - "intel_rapl_perf config not found!!"

2020-08-26 Thread Changbin Du
On Tue, Aug 25, 2020 at 02:34:34PM -0700, Randy Dunlap wrote:
> On 8/25/20 2:12 PM, Randy Dunlap wrote:
> >> On Tue, Aug 25, 2020 at 2:13 PM Randy Dunlap  wrote:
> >>>
> >>> so intel_rapl_perf is listed in your lsmod.cfg file:
> >>> intel_rapl_perf16384  2
> >>>
> >>> You say Linux 5.8.3.  I'm guessing that your "make localmodconfig" tree
> >>> is Linux 5.8.3 (?).  What kernel version are you running?
> >>> I think that it's older, and some file/module names have changed since 
> >>> then.
> > 
> > On 8/25/20 1:34 PM, Nathan Royce wrote:
> >> Correct. I'm building for 5.8.3 and I'm currently on 5.7.4 (1 month
> >> doesn't seem particularly old).
> > 
> > Yes, things can change quickly.
> > 
> > 
> > I don't see any support in streamline_config.pl for Kconfig symbols
> > and/or modules whose names have changed.  Trying to do something
> > like that would be a never-ending job (a la job security).
> > 
> > At least it gave you a warning that it couldn't find a Kconfig symbol
> > for that module.
> > 
> > 
> > From your original email:
> > | I'm going to assume it has something to do with the naming and it's
> > | supposed to be associated with "Intel/AMD rapl performance events
> > | (CONFIG_PERF_EVENTS_INTEL_RAPL)" which I already have set to 'Y'.
> > 
> > Yes, commit fd3ae1e1587d64ef8cc8e361903d33625458073e changed the module name
> > since it now supports both Intel and AMD.
> > 
> > 
> > | Right below that, I also get 'Use of uninitialized value
> > | $ENV{"LMC_KEEP"} in split at ./scripts/kconfig/streamline_config.pl
> > | line 596.', but again that is the sort of thing that may warrant a new
> > | email specific to localmodconfig author(s). But again maybe not
> > | because I take it more as a warning given I don't make use of
> > | LMC_KEEP.
> > 
> > 
> > @Changbin: can you fix this little bug in streamline_config.pl, please? 
> > ^
This was tested before. Is this a perl version issue?

changbin@vultr:~$ cat a.pl
my @preserved_kconfigs = split(/:/,$ENV{LMC_KEEP});
print("@preserved_kconfigs")
changbin@vultr:~$ perl a.pl 
changbin@vultr:~$ perl -v  
This is perl 5, version 26, subversion 1 (v5.26.1) built for 
x86_64-linux-gnu-thread-multi
(with 67 registered patches, see perl -V for more detail)

Copyright 1987-2017, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.
> 
> Changing email address for Changbin.
> Plus I made the quick patch for streamline_config.pl (below)
> although I haven't tested it.
> 
> ---
> From: Randy Dunlap 
> 
> A user reported:
> 'Use of uninitialized value $ENV{"LMC_KEEP"} in split at
>  ./scripts/kconfig/streamline_config.pl line 596.'
> 
> so first check that $ENV{LMC_KEEP} is defined before trying
> to use it.
> 
> Fixes: c027b02d89fd ("streamline_config.pl: add LMC_KEEP to preserve some 
> kconfigs")
> Signed-off-by: Randy Dunlap 
> Cc: Changbin Du 
> Cc: Steven Rostedt (VMware) 
> Cc: Masahiro Yamada 
> ---
>  scripts/kconfig/streamline_config.pl |5 -
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> --- linux-next-20200825.orig/scripts/kconfig/streamline_config.pl
> +++ linux-next-20200825/scripts/kconfig/streamline_config.pl
> @@ -593,7 +593,10 @@ while ($repeat) {
>  }
>  
>  my %setconfigs;
> -my @preserved_kconfigs = split(/:/,$ENV{LMC_KEEP});
> +my @preserved_kconfigs;
> +if (defined($ENV{'LMC_KEEP'})) {
> + @preserved_kconfigs = split(/:/,$ENV{LMC_KEEP});
> +}
>  
>  sub in_preserved_kconfigs {
>  my $kconfig = $config2kfile{$_[0]};
> 

-- 
Cheers,
Changbin Du


[PATCH] perf: ftrace: Add filter support for option -F/--funcs

2020-08-22 Thread Changbin Du
Same as 'perf probe -F', this patch adds filter support for the ftrace
subcommand option '-F, --funcs <[FILTER]>'.

Here is an example that only lists functions which start with 'vfs_':
$ sudo perf ftrace -F vfs_*
vfs_fadvise
vfs_fallocate
vfs_truncate
vfs_open
vfs_setpos
vfs_llseek
vfs_readf
vfs_writef
...

Suggested-by: Arnaldo Carvalho de Melo 
Signed-off-by: Changbin Du 
---
 tools/perf/Documentation/perf-ftrace.txt |  3 +-
 tools/perf/builtin-ftrace.c  | 84 ++--
 2 files changed, 80 insertions(+), 7 deletions(-)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 78358af9a1c4..1e91121bac0f 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -33,7 +33,8 @@ OPTIONS
 
 -F::
 --funcs::
-List all available functions to trace.
+List available functions to trace. It accepts a pattern to
+only list interested functions.
 
 -p::
 --pid=::
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 1d44bc2f63d8..9366fad591dc 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -25,6 +25,7 @@
 #include "target.h"
 #include "cpumap.h"
 #include "thread_map.h"
+#include "strfilter.h"
 #include "util/cap.h"
 #include "util/config.h"
 #include "util/units.h"
@@ -36,7 +37,6 @@ struct perf_ftrace {
struct evlist   *evlist;
struct target   target;
const char  *tracer;
-   boollist_avail_functions;
struct list_headfilters;
struct list_headnotrace;
struct list_headgraph_funcs;
@@ -181,6 +181,40 @@ static int read_tracing_file_to_stdout(const char *name)
return ret;
 }
 
+static int read_tracing_file_by_line(const char *name,
+void (*cb)(char *str, void *arg),
+void *cb_arg)
+{
+   char *line = NULL;
+   size_t len = 0;
+   char *file;
+   FILE *fp;
+
+   file = get_tracing_file(name);
+   if (!file) {
+   pr_debug("cannot get tracing file: %s\n", name);
+   return -1;
+   }
+
+   fp = fopen(file, "r");
+   if (fp == NULL) {
+   pr_debug("cannot open tracing file: %s\n", name);
+   put_tracing_file(file);
+   return -1;
+   }
+
+   while (getline(&line, &len, fp) != -1) {
+   cb(line, cb_arg);
+   }
+
+   if (line)
+   free(line);
+
+   fclose(fp);
+   put_tracing_file(file);
+   return 0;
+}
+
 static int write_tracing_file_int(const char *name, int value)
 {
char buf[16];
@@ -557,9 +591,6 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
signal(SIGCHLD, sig_handler);
signal(SIGPIPE, sig_handler);
 
-   if (ftrace->list_avail_functions)
-   return 
read_tracing_file_to_stdout("available_filter_functions");
-
if (reset_tracing_files(ftrace) < 0) {
pr_err("failed to reset ftrace\n");
goto out;
@@ -683,6 +714,46 @@ static int perf_ftrace_config(const char *var, const char 
*value, void *cb)
return -1;
 }
 
+static void list_function_cb(char *str, void *arg)
+{
+   struct strfilter *filter = (struct strfilter *)arg;
+
+   if (strfilter__compare(filter, str))
+   printf("%s", str);
+}
+
+static int opt_list_avail_functions(const struct option *opt __maybe_unused,
+   const char *str, int unset)
+{
+   struct strfilter *filter;
+   const char *err = NULL;
+   int ret;
+
+   if (unset || !str)
+   return -1;
+
+   filter = strfilter__new(str, &err);
+   if (!filter)
+   return err ? -EINVAL : -ENOMEM;
+
+   ret = strfilter__or(filter, str, &err);
+   if (ret == -EINVAL) {
+   pr_err("Filter parse error at %td.\n", err - str + 1);
+   pr_err("Source: \"%s\"\n", str);
+   pr_err(" %*c\n", (int)(err - str + 1), '^');
+   strfilter__delete(filter);
+   return ret;
+   }
+
+   ret = read_tracing_file_by_line("available_filter_functions",
+   list_function_cb, filter);
+   strfilter__delete(filter);
+   if (ret < 0)
+   return ret;
+
+   exit(0);
+}
+
 static int parse_filter_func(const struct option *opt, const char *str,
 int unset __maybe_unused)
 {
@@ -817,8 +888,9 @@ int cmd_ftrace(int argc, const char **argv)
const struct option ftr

Re: [PATCH v8 02/18] perf ftrace: add option '-F/--funcs' to list available functions

2020-08-20 Thread Changbin Du
On Fri, Aug 14, 2020 at 08:35:35AM -0300, Arnaldo Carvalho de Melo wrote:
> Em Sat, Aug 08, 2020 at 10:31:25AM +0800, Changbin Du escreveu:
> > This adds an option '-F/--funcs' to list all available functions to trace,
> > which is read from tracing file 'available_filter_functions'.
> > 
> > $ sudo ./perf ftrace -F | head
> > trace_initcall_finish_cb
> > initcall_blacklisted
> > do_one_initcall
> > do_one_initcall
> > trace_initcall_start_cb
> > run_init_process
> > try_to_run_init_process
> > match_dev_by_label
> > match_dev_by_uuid
> > rootfs_init_fs_context
> > 
> > Signed-off-by: Changbin Du 
> > 
> > ---
> > v3: fix return value issue.
> > v2: option name '-l/--list-functions' -> '-F/--funcs'
> > ---
> >  tools/perf/Documentation/perf-ftrace.txt |  4 +++
> >  tools/perf/builtin-ftrace.c  | 46 
> >  2 files changed, 50 insertions(+)
> > 
> > diff --git a/tools/perf/Documentation/perf-ftrace.txt 
> > b/tools/perf/Documentation/perf-ftrace.txt
> > index 821d4d334a09..4f5628445a63 100644
> > --- a/tools/perf/Documentation/perf-ftrace.txt
> > +++ b/tools/perf/Documentation/perf-ftrace.txt
> > @@ -31,6 +31,10 @@ OPTIONS
> >  --verbose=::
> >  Verbosity level.
> >  
> > +-F::
> > +--funcs::
> > +List all available functions to trace.
> > +
> >  -p::
> >  --pid=::
> > Trace on existing process id (comma separated list).
> > diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
> > index 048a11192b59..1ebf71ecc1a8 100644
> > --- a/tools/perf/builtin-ftrace.c
> > +++ b/tools/perf/builtin-ftrace.c
> > @@ -33,6 +33,7 @@ struct perf_ftrace {
> > struct evlist   *evlist;
> > struct target   target;
> > const char  *tracer;
> > +   boollist_avail_functions;
> > struct list_headfilters;
> > struct list_headnotrace;
> > struct list_headgraph_funcs;
> > @@ -128,6 +129,46 @@ static int append_tracing_file(const char *name, const 
> > char *val)
> > return __write_tracing_file(name, val, true);
> >  }
> >  
> > +static int read_tracing_file_to_stdout(const char *name)
> > +{
> > +   char buf[4096];
> > +   char *file;
> > +   int fd;
> > +   int ret = -1;
> > +
> > +   file = get_tracing_file(name);
> > +   if (!file) {
> > +   pr_debug("cannot get tracing file: %s\n", name);
> > +   return -1;
> > +   }
> > +
> > +   fd = open(file, O_RDONLY);
> > +   if (fd < 0) {
> > +   pr_debug("cannot open tracing file: %s: %s\n",
> > +name, str_error_r(errno, buf, sizeof(buf)));
> > +   goto out;
> > +   }
> > +
> > +   /* read contents to stdout */
> > +   while (true) {
> > +   int n = read(fd, buf, sizeof(buf));
> > +   if (n == 0)
> > +   break;
> > +   else if (n < 0)
> > +   goto out_close;
> > +
> > +   if (fwrite(buf, n, 1, stdout) != 1)
> > +   goto out_close;
> > +   }
> > +   ret = 0;
> > +
> > +out_close:
> > +   close(fd);
> > +out:
> > +   put_tracing_file(file);
> > +   return ret;
> > +}
> > +
> >  static int reset_tracing_cpu(void);
> >  static void reset_tracing_filters(void);
> >  
> > @@ -302,6 +343,9 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
> > argc, const char **argv)
> > signal(SIGCHLD, sig_handler);
> > signal(SIGPIPE, sig_handler);
> >  
> > +   if (ftrace->list_avail_functions)
> > +   return 
> > read_tracing_file_to_stdout("available_filter_functions");
> > +
> > if (reset_tracing_files(ftrace) < 0) {
> > pr_err("failed to reset ftrace\n");
> > goto out;
> > @@ -487,6 +531,8 @@ int cmd_ftrace(int argc, const char **argv)
> > const struct option ftrace_options[] = {
> > OPT_STRING('t', "tracer", &ftrace.tracer, "tracer",
> >"tracer to use: function_graph(default) or function"),
> > +   OPT_BOOLEAN('F', "funcs", &ftrace.list_avail_functions,
> > +   "Show available functions to filter"),
> 
> A boolean? I guess this can be a first step, but why not do it like
> 'perf probe' and accept a patterna? Allows for less typing:
> 
>   # perf probe -h -F
> 
> -F, --funcs <[FILTER]>
>   Show potential probe-able functions.
> 
> [root@quaco ~]#
> 
> # perf probe -F '*btf_parse*'
> btf_parse_hdr
> btf_parse_str_sec
> btf_parse_vmlinux
> #
> # perf ftrace -F | grep btf_parse
> btf_parse_str_sec
> btf_parse_hdr
> btf_parse_vmlinux
> #
> 
> I'm applying this to make progress, but please consider sending a patch
> to make this behave in the same way as 'perf probe'.
>
No problem, I'll try to provide similar behaviour for this. Thanks.

> - Arnaldo
> 
> 
> > OPT_STRING('p', "pid", &ftrace.target.pid, "pid",
> >"trace on existing process id"),
> > OPT_INCR('v', "verbose", &verbose,
> > -- 
> > 2.25.1
> > 
> 
> -- 
> 
> - Arnaldo

-- 
Cheers,
Changbin Du


Re: [PATCH v8 08/18] perf ftrace: add support for tracing option 'func_stack_trace'

2020-08-20 Thread Changbin Du
On Fri, Aug 14, 2020 at 09:24:40AM -0300, Arnaldo Carvalho de Melo wrote:
> Em Sat, Aug 08, 2020 at 10:31:31AM +0800, Changbin Du escreveu:
> > This adds support to display call trace for function tracer. To do this,
> > just specify a '--func-opts call-graph' option.
> 
> Applied, thanks for providing the usage example and the output of the
> tool, please consider making this more compact and similar to the other
> perf tools as:
> 
># perf ftrace -g -T vfs_read
> 
>   # perf report -h -g
>   
>Usage: perf report []
>   
>   -g, --call-graph 
> 
> Display call graph (stack chain/backtrace):
>   
>   print_type: call graph printing style 
> (graph|flat|fractal|folded|none)
>   threshold:  minimum call graph 
> inclusion threshold ()
>   print_limit:maximum number of call 
> graph entry ()
>   order:  call graph order 
> (caller|callee)
>   sort_key:   call graph sort key 
> (function|address)
>   branch: include last branch info to 
> call graph (branch)
>   value:  call graph value 
> (percent|period|count)
>   
>   Default: graph,0.5,caller,function,percent
>   
>   # 
> 
> Is there a way to ask for a limit in the number of levels? That is
> similar to /proc/sys/kernel/perf_event_max_stack (system wide) and
> perf_event_attr.sample_max_stack (per event)?
> 
No, there is no such limit for function tracer yet (kernel doesn't support it).
It just backtraces from current to top.

For graph tracer, the option is --graph-opts depth=.

> One can ask for that per event:
> 
>   # perf trace -e sched:*_wakeup/max-stack=2/ -e sched:*switch/max-stack=5/ 
> --max-events=4
>  0.000 migration/0/12 sched:sched_switch(prev_comm: "migration/0", 
> prev_pid: 12 (migration/0), prev_prio: 0, prev_state: 1, next_comm: 
> "swapper/0", next_pid: 0, next_prio: 120)
>__schedule ([kernel.kallsyms])
>__schedule ([kernel.kallsyms])
>schedule ([kernel.kallsyms])
>smpboot_thread_fn ([kernel.kallsyms])
>kthread ([kernel.kallsyms])
>  2.381 :0/0 sched:sched_wakeup(comm: "PacerThread", pid: 111637 
> (PacerThread), prio: 120, success: 1, target_cpu: 0)
>ttwu_do_wakeup ([kernel.kallsyms])
>ttwu_do_wakeup ([kernel.kallsyms])
>  2.387 :0/0 sched:sched_switch(prev_comm: "swapper/0", prev_pid: 0, 
> prev_prio: 120, prev_state: 0, next_comm: "PacerThread", next_pid: 111637 
> (PacerThread), next_prio: 120)
>__schedule ([kernel.kallsyms])
>__schedule ([kernel.kallsyms])
>schedule_idle ([kernel.kallsyms])
>do_idle ([kernel.kallsyms])
>cpu_startup_entry ([kernel.kallsyms])
>  2.410 PacerThread/111637 sched:sched_switch(prev_comm: "PacerThread", 
> prev_pid: 111637 (PacerThread), prev_prio: 120, prev_state: 1, next_comm: 
> "swapper/0", next_pid: 0, next_prio: 120)
>__schedule ([kernel.kallsyms])
>__schedule ([kernel.kallsyms])
>schedule ([kernel.kallsyms])
>futex_wait_queue_me ([kernel.kallsyms])
>futex_wait ([kernel.kallsyms])
>   #
> 
> - Arnaldo
>  
> > $ sudo perf ftrace -T vfs_read --func-opts call-graph
> >  iio-sensor-prox-855   [003]   6168.369657: vfs_read <-ksys_read
> >  iio-sensor-prox-855   [003]   6168.369677: 
> >  => vfs_read
> >  => ksys_read
> >  => __x64_sys_read
> >  => do_syscall_64
> >  => entry_SYSCALL_64_after_hwframe
> >  ...
> > 
> > Signed-off-by: Changbin Du 
> > 
> > ---
> > v3: switch to uniform option --func-opts.
> > v2: option name '-s' -> '--func-call-graph'
> > ---
> >  tools/perf/Documentation/perf-ftrace.txt |  4 +++
> >  tools/perf/builtin-ftrace.c  | 42 
> >  2 files changed, 46 insert

Re: [PATCH v8 11/18] perf ftrace: add support for tracing option 'irq-info'

2020-08-20 Thread Changbin Du
On Fri, Aug 14, 2020 at 09:28:07AM -0300, Arnaldo Carvalho de Melo wrote:
> Em Sat, Aug 08, 2020 at 10:31:34AM +0800, Changbin Du escreveu:
> > This adds support to display irq context info for function tracer. To do
> > this, just specify a '--func-opts irq-info' option.
> 
> Applied, ditto about adding an example to perf-ftrace.txt
>
no problem, I will do it some days later. Thanks.

> > Signed-off-by: Changbin Du 
> > ---
> >  tools/perf/Documentation/perf-ftrace.txt |  1 +
> >  tools/perf/builtin-ftrace.c  | 21 -
> >  2 files changed, 21 insertions(+), 1 deletion(-)
> > 
> > diff --git a/tools/perf/Documentation/perf-ftrace.txt 
> > b/tools/perf/Documentation/perf-ftrace.txt
> > index fca55ac55ff3..37ea3ea97922 100644
> > --- a/tools/perf/Documentation/perf-ftrace.txt
> > +++ b/tools/perf/Documentation/perf-ftrace.txt
> > @@ -79,6 +79,7 @@ OPTIONS
> >  --func-opts::
> > List of options allowed to set:
> >   call-graph - Display kernel stack trace for function tracer.
> > + irq-info   - Display irq context info for function tracer.
> >  
> >  -G::
> >  --graph-funcs=::
> > diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
> > index b4c821be4fb5..d1241febe143 100644
> > --- a/tools/perf/builtin-ftrace.c
> > +++ b/tools/perf/builtin-ftrace.c
> > @@ -44,6 +44,7 @@ struct perf_ftrace {
> > unsigned long   percpu_buffer_size;
> > boolinherit;
> > int func_stack_trace;
> > +   int func_irq_info;
> > int graph_nosleep_time;
> > int graph_noirqs;
> >  };
> > @@ -209,6 +210,7 @@ static void reset_tracing_options(struct perf_ftrace 
> > *ftrace __maybe_unused)
> > write_tracing_option_file("func_stack_trace", "0");
> > write_tracing_option_file("sleep-time", "1");
> > write_tracing_option_file("funcgraph-irqs", "1");
> > +   write_tracing_option_file("irq-info", "0");
> >  }
> >  
> >  static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
> > @@ -296,6 +298,17 @@ static int set_tracing_func_stack_trace(struct 
> > perf_ftrace *ftrace)
> > return 0;
> >  }
> >  
> > +static int set_tracing_func_irqinfo(struct perf_ftrace *ftrace)
> > +{
> > +   if (!ftrace->func_irq_info)
> > +   return 0;
> > +
> > +   if (write_tracing_option_file("irq-info", "1") < 0)
> > +   return -1;
> > +
> > +   return 0;
> > +}
> > +
> >  static int reset_tracing_cpu(void)
> >  {
> > struct perf_cpu_map *cpumap = perf_cpu_map__new(NULL);
> > @@ -471,6 +484,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, 
> > int argc, const char **argv)
> > goto out_reset;
> > }
> >  
> > +   if (set_tracing_func_irqinfo(ftrace) < 0) {
> > +   pr_err("failed to set tracing option irq-info\n");
> > +   goto out_reset;
> > +   }
> > +
> > if (set_tracing_filters(ftrace) < 0) {
> > pr_err("failed to set tracing filters\n");
> > goto out_reset;
> > @@ -660,6 +678,7 @@ static int parse_func_tracer_opts(const struct option 
> > *opt,
> > struct perf_ftrace *ftrace = (struct perf_ftrace *) opt->value;
> > struct sublevel_option func_tracer_opts[] = {
> > { .name = "call-graph", .value_ptr = &ftrace->func_stack_trace 
> > },
> > +   { .name = "irq-info",   .value_ptr = &ftrace->func_irq_info },
> > { .name = NULL, }
> > };
> >  
> > @@ -742,7 +761,7 @@ int cmd_ftrace(int argc, const char **argv)
> > OPT_CALLBACK('N', "notrace-funcs", &ftrace.notrace, "func",
> >  "do not trace given functions", parse_filter_func),
> > OPT_CALLBACK(0, "func-opts", &ftrace, "options",
> > -"function tracer options, available options: call-graph",
> > +"function tracer options, available options: 
> > call-graph,irq-info",
> >  parse_func_tracer_opts),
> > OPT_CALLBACK('G', "graph-funcs", &ftrace.graph_funcs, "func",
> >  "trace given functions using function_graph tracer",
> > -- 
> > 2.25.1
> > 
> 
> -- 
> 
> - Arnaldo

-- 
Cheers,
Changbin Du


Re: [PATCH v8 13/18] perf ftrace: add support for trace option tracing_thresh

2020-08-20 Thread Changbin Du
On Fri, Aug 14, 2020 at 09:33:10AM -0300, Arnaldo Carvalho de Melo wrote:
> Em Sat, Aug 08, 2020 at 10:31:36AM +0800, Changbin Du escreveu:
> > This adds an option '--graph-opts thresh' to setup trace duration
> > threshold for funcgraph tracer.
> 
> Applied, please consider making --duration an alias for this, as this is
> also available in 'perf trace':
> 
> [root@quaco ~]# perf trace --duration 500 --max-events=5
>369.860 gnome-shell/2084 poll(ufds: 0x559577983080, nfds: 21, 
> timeout_msecs: 7194) = 1
>493.654 pool-geoclue/386046 futex(uaddr: 0x56024843b610, op: 
> WAIT|PRIVATE_FLAG, val: 1201, utime: 0x7f32bd7f9cc0) = -1 ETIMEDOUT 
> (Connection timed out)
> 71.604 WebRTC_Worker/111634 futex(uaddr: 0x7fb4c364d608, op: 
> WAIT_BITSET|PRIVATE_FLAG, val: 0, utime: 0x7fb4c364d410, val3: MATCH_ANY) = 
> -1 ETIMEDOUT (Connection timed out)
>601.645 pool-gsd-smart/2469 clock_nanosleep(which_clock: 0, flags: 0, 
> rqtp: 0x7fb82cbd1cf0, rmtp: 0x7fb82cbd1d00) = 0
>623.823 chromium-brows/92363 futex(uaddr: 0x7ffcfd064e38, op: 
> WAIT_BITSET|PRIVATE_FLAG, val: 0, utime: 0x7ffcfd064c40, val3: MATCH_ANY) = 
> -1 ETIMEDOUT (Connection timed out)
> [root@quaco ~]#
> 
>   $ perf trace -h duration
> 
> --duration 
>   show only events with duration > N.M ms
> 
>   $
> 
> This way one would be able to do:
> 
>   # perf trace --duration N.M
> 
> To see at syscall level, then add 'f':
> 
>   # perf ftrace --duration N.M
> 
> To see at kernel function level. Switching from one perf tool to another
> with such ease is the main objective here, I'd say :-)
>
Sure. Currently the unit for ftrace is 'ns'. I could change it to 'ms' at perf
level.

> - Arnaldo
>  
> > $ sudo ./perf ftrace -G '*' --graph-opts thresh=100
> >  3) ! 184.060 us  |} /* schedule */
> >  3) ! 185.600 us  |  } /* exit_to_usermode_loop */
> >  2) ! 225.989 us  |} /* schedule_idle */
> >  2) # 4140.051 us |  } /* do_idle */
> > 
> > Signed-off-by: Changbin Du 
> > ---
> >  tools/perf/Documentation/perf-ftrace.txt |  1 +
> >  tools/perf/builtin-ftrace.c  | 26 +++-
> >  2 files changed, 26 insertions(+), 1 deletion(-)
> > 
> > diff --git a/tools/perf/Documentation/perf-ftrace.txt 
> > b/tools/perf/Documentation/perf-ftrace.txt
> > index a2056aaf2ece..6fa927e5971b 100644
> > --- a/tools/perf/Documentation/perf-ftrace.txt
> > +++ b/tools/perf/Documentation/perf-ftrace.txt
> > @@ -107,6 +107,7 @@ OPTIONS
> >   nosleep-time - Measure on-CPU time only for function_graph tracer.
> >   noirqs   - Ignore functions that happen inside interrupt.
> >   verbose  - Show process names, PIDs, timestamps, etc.
> > + thresh=   - Setup trace duration threshold in microseconds.
> >  
> >  SEE ALSO
> >  
> > diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
> > index 8ee5287bd84a..ca61f8b8bbf6 100644
> > --- a/tools/perf/builtin-ftrace.c
> > +++ b/tools/perf/builtin-ftrace.c
> > @@ -48,6 +48,7 @@ struct perf_ftrace {
> > int graph_nosleep_time;
> > int graph_noirqs;
> > int graph_verbose;
> > +   int graph_thresh;
> >  };
> >  
> >  struct filter_entry {
> > @@ -234,6 +235,9 @@ static int reset_tracing_files(struct perf_ftrace 
> > *ftrace __maybe_unused)
> > if (write_tracing_file("max_graph_depth", "0") < 0)
> > return -1;
> >  
> > +   if (write_tracing_file("tracing_thresh", "0") < 0)
> > +   return -1;
> > +
> > reset_tracing_filters();
> > reset_tracing_options(ftrace);
> > return 0;
> > @@ -446,6 +450,20 @@ static int set_tracing_funcgraph_verbose(struct 
> > perf_ftrace *ftrace)
> > return 0;
> >  }
> >  
> > +static int set_tracing_thresh(struct perf_ftrace *ftrace)
> > +{
> > +   int ret;
> > +
> > +   if (ftrace->graph_thresh == 0)
> > +   return 0;
> > +
> > +   ret = write_tracing_file_int("tracing_thresh", ftrace->graph_thresh);
> > +   if (ret < 0)
> > +   return ret;
> > +
> > +   return 0;
> > +}
> > +
> >  static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
> > **argv)
> >  {
> > char *trace_file;
> > @@ -545,6 +563,11 @@ static int __cmd_ftrace(struct

[PATCH v8 18/18] perf ftrace: add change log

2020-08-07 Thread Changbin Du
Add a change log after previous enhancements.

Signed-off-by: Changbin Du 
---
 tools/perf/builtin-ftrace.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 9da38dc8b542..167f1f57aba3 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -3,6 +3,7 @@
  * builtin-ftrace.c
  *
  * Copyright (c) 2013  LG Electronics,  Namhyung Kim 
+ * Copyright (c) 2020  Changbin Du , significant 
enhancement.
  */
 
 #include "builtin.h"
-- 
2.25.1



[PATCH v8 15/18] perf ftrace: add option -D/--delay to delay tracing

2020-08-07 Thread Changbin Du
This adds an option '-D/--delay' to allow us to start tracing some
times later after workload is launched.

Signed-off-by: Changbin Du 
---
 tools/perf/Documentation/perf-ftrace.txt |  4 
 tools/perf/builtin-ftrace.c  | 19 ---
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 08216634d2bc..29c684b3b3fd 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -39,6 +39,10 @@ OPTIONS
 --pid=::
Trace on existing process id (comma separated list).
 
+-D::
+--delay::
+   Time (ms) to wait before starting tracing after program start.
+
 -a::
 --all-cpus::
Force system-wide collection.  Scripts run without a 
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index bc3b35d18167..5f9a9ebea0a2 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -49,6 +49,7 @@ struct perf_ftrace {
int graph_noirqs;
int graph_verbose;
int graph_thresh;
+   unsigned intinitial_delay;
 };
 
 struct filter_entry {
@@ -596,13 +597,23 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
/* display column headers */
read_tracing_file_to_stdout("trace");
 
-   if (write_tracing_file("tracing_on", "1") < 0) {
-   pr_err("can't enable tracing\n");
-   goto out_close_fd;
+   if (!ftrace->initial_delay) {
+   if (write_tracing_file("tracing_on", "1") < 0) {
+   pr_err("can't enable tracing\n");
+   goto out_close_fd;
+   }
}
 
perf_evlist__start_workload(ftrace->evlist);
 
+   if (ftrace->initial_delay) {
+   usleep(ftrace->initial_delay * 1000);
+   if (write_tracing_file("tracing_on", "1") < 0) {
+   pr_err("can't enable tracing\n");
+   goto out_close_fd;
+   }
+   }
+
while (!done) {
if (poll(&pollfd, 1, -1) < 0)
break;
@@ -827,6 +838,8 @@ int cmd_ftrace(int argc, const char **argv)
 "size of per cpu buffer", parse_buffer_size),
OPT_BOOLEAN(0, "inherit", &ftrace.inherit,
"trace children processes"),
+   OPT_UINTEGER('D', "delay", &ftrace.initial_delay,
+"ms to wait before starting tracing after program start"),
OPT_END()
};
 
-- 
2.25.1



[PATCH v8 17/18] perf: ftrace: Add set_tracing_options() to set all trace options

2020-08-07 Thread Changbin Du
Now the __cmd_ftrace() becomes a bit long. This moves the trace
option setting code to a separate function set_tracing_options().

Suggested-by: Namhyung Kim 
Signed-off-by: Changbin Du 
---
 tools/perf/builtin-ftrace.c | 118 +++-
 1 file changed, 63 insertions(+), 55 deletions(-)

diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 13abb737fd12..9da38dc8b542 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -465,110 +465,118 @@ static int set_tracing_thresh(struct perf_ftrace 
*ftrace)
return 0;
 }
 
-static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
**argv)
+static int set_tracing_options(struct perf_ftrace *ftrace)
 {
-   char *trace_file;
-   int trace_fd;
-   char buf[4096];
-   struct pollfd pollfd = {
-   .events = POLLIN,
-   };
-
-   if (!(perf_cap__capable(CAP_PERFMON) ||
- perf_cap__capable(CAP_SYS_ADMIN))) {
-   pr_err("ftrace only works for %s!\n",
-#ifdef HAVE_LIBCAP_SUPPORT
-   "users with the CAP_PERFMON or CAP_SYS_ADMIN capability"
-#else
-   "root"
-#endif
-   );
-   return -1;
-   }
-
-   signal(SIGINT, sig_handler);
-   signal(SIGUSR1, sig_handler);
-   signal(SIGCHLD, sig_handler);
-   signal(SIGPIPE, sig_handler);
-
-   if (ftrace->list_avail_functions)
-   return 
read_tracing_file_to_stdout("available_filter_functions");
-
-   if (reset_tracing_files(ftrace) < 0) {
-   pr_err("failed to reset ftrace\n");
-   goto out;
-   }
-
-   /* reset ftrace buffer */
-   if (write_tracing_file("trace", "0") < 0)
-   goto out;
-
-   if (argc && perf_evlist__prepare_workload(ftrace->evlist,
-   &ftrace->target, argv, false,
-   ftrace__workload_exec_failed_signal) < 0) {
-   goto out;
-   }
-
if (set_tracing_pid(ftrace) < 0) {
pr_err("failed to set ftrace pid\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_cpu(ftrace) < 0) {
pr_err("failed to set tracing cpumask\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_func_stack_trace(ftrace) < 0) {
pr_err("failed to set tracing option func_stack_trace\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_func_irqinfo(ftrace) < 0) {
pr_err("failed to set tracing option irq-info\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_filters(ftrace) < 0) {
pr_err("failed to set tracing filters\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_depth(ftrace) < 0) {
pr_err("failed to set graph depth\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_percpu_buffer_size(ftrace) < 0) {
pr_err("failed to set tracing per-cpu buffer size\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_trace_inherit(ftrace) < 0) {
pr_err("failed to set tracing option function-fork\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_sleep_time(ftrace) < 0) {
pr_err("failed to set tracing option sleep-time\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_funcgraph_irqs(ftrace) < 0) {
pr_err("failed to set tracing option funcgraph-irqs\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_funcgraph_verbose(ftrace) < 0) {
pr_err("failed to set tracing option 
funcgraph-proc/funcgraph-abstime\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_thresh(ftrace) < 0) {
pr_err("failed to set tracing thresh\n");
-   goto out_reset;
+   return -1;
+   }
+
+   return 0;
+}
+
+static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
**argv)
+{
+   char *trace_file;
+   int trace_fd;
+   char buf[4096];
+   struct pollfd pollfd = {
+   .events = POLLIN,
+   };
+
+   if (!(perf_cap__capable(CAP_PERFMON) ||
+ perf_cap__capable(CAP_SYS_ADMIN))) {
+   pr_err("ftrace only works for %s!\n",
+#ifdef HAVE_LIBCAP_SUPPORT

[PATCH v8 09/18] perf ftrace: add support for trace option sleep-time

2020-08-07 Thread Changbin Du
This adds an option '--graph-opts nosleep-time' which allow us
only to measure on-CPU time. This option is function_graph tracer
only.

Signed-off-by: Changbin Du 

---
v3: switch to uniform option --graph-opts.
v2: option name '--nosleep-time' -> '--graph-nosleep-time'.
---
 tools/perf/Documentation/perf-ftrace.txt |  4 +++
 tools/perf/builtin-ftrace.c  | 41 
 2 files changed, 45 insertions(+)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 8f08ad0992c2..3380a2e2c9ad 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -101,6 +101,10 @@ OPTIONS
 --graph-depth=::
Set max depth for function graph tracer to follow
 
+--graph-opts::
+   List of options allowed to set:
+ nosleep-time - Measure on-CPU time only for function_graph tracer.
+
 SEE ALSO
 
 linkperf:perf-record[1], linkperf:perf-trace[1]
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 469b89748c42..47d63bba6a48 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -44,6 +44,7 @@ struct perf_ftrace {
unsigned long   percpu_buffer_size;
boolinherit;
int func_stack_trace;
+   int graph_nosleep_time;
 };
 
 struct filter_entry {
@@ -205,6 +206,7 @@ static void reset_tracing_options(struct perf_ftrace 
*ftrace __maybe_unused)
 {
write_tracing_option_file("function-fork", "0");
write_tracing_option_file("func_stack_trace", "0");
+   write_tracing_option_file("sleep-time", "1");
 }
 
 static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
@@ -386,6 +388,17 @@ static int set_tracing_trace_inherit(struct perf_ftrace 
*ftrace)
return 0;
 }
 
+static int set_tracing_sleep_time(struct perf_ftrace *ftrace)
+{
+   if (!ftrace->graph_nosleep_time)
+   return 0;
+
+   if (write_tracing_option_file("sleep-time", "0") < 0)
+   return -1;
+
+   return 0;
+}
+
 static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
**argv)
 {
char *trace_file;
@@ -465,6 +478,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
goto out_reset;
}
 
+   if (set_tracing_sleep_time(ftrace) < 0) {
+   pr_err("failed to set tracing option sleep-time\n");
+   goto out_reset;
+   }
+
if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
goto out_reset;
@@ -637,6 +655,26 @@ static int parse_func_tracer_opts(const struct option *opt,
return 0;
 }
 
+static int parse_graph_tracer_opts(const struct option *opt,
+ const char *str, int unset)
+{
+   int ret;
+   struct perf_ftrace *ftrace = (struct perf_ftrace *) opt->value;
+   struct sublevel_option graph_tracer_opts[] = {
+   { .name = "nosleep-time",   .value_ptr = 
&ftrace->graph_nosleep_time },
+   { .name = NULL, }
+   };
+
+   if (unset)
+   return 0;
+
+   ret = perf_parse_sublevel_options(str, graph_tracer_opts);
+   if (ret)
+   return ret;
+
+   return 0;
+}
+
 static void select_tracer(struct perf_ftrace *ftrace)
 {
bool graph = !list_empty(&ftrace->graph_funcs) ||
@@ -694,6 +732,9 @@ int cmd_ftrace(int argc, const char **argv)
 "Set nograph filter on given functions", 
parse_filter_func),
OPT_INTEGER('D', "graph-depth", &ftrace.graph_depth,
"Max depth for function graph tracer"),
+   OPT_CALLBACK(0, "graph-opts", &ftrace, "options",
+"graph tracer options, available options: nosleep-time",
+parse_graph_tracer_opts),
OPT_CALLBACK('m', "buffer-size", &ftrace.percpu_buffer_size, "size",
 "size of per cpu buffer", parse_buffer_size),
OPT_BOOLEAN(0, "inherit", &ftrace.inherit,
-- 
2.25.1



[PATCH v8 13/18] perf ftrace: add support for trace option tracing_thresh

2020-08-07 Thread Changbin Du
This adds an option '--graph-opts thresh' to setup trace duration
threshold for funcgraph tracer.

$ sudo ./perf ftrace -G '*' --graph-opts thresh=100
 3) ! 184.060 us  |} /* schedule */
 3) ! 185.600 us  |  } /* exit_to_usermode_loop */
 2) ! 225.989 us  |} /* schedule_idle */
 2) # 4140.051 us |  } /* do_idle */

Signed-off-by: Changbin Du 
---
 tools/perf/Documentation/perf-ftrace.txt |  1 +
 tools/perf/builtin-ftrace.c  | 26 +++-
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index a2056aaf2ece..6fa927e5971b 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -107,6 +107,7 @@ OPTIONS
  nosleep-time - Measure on-CPU time only for function_graph tracer.
  noirqs   - Ignore functions that happen inside interrupt.
  verbose  - Show process names, PIDs, timestamps, etc.
+ thresh=   - Setup trace duration threshold in microseconds.
 
 SEE ALSO
 
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 8ee5287bd84a..ca61f8b8bbf6 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -48,6 +48,7 @@ struct perf_ftrace {
int graph_nosleep_time;
int graph_noirqs;
int graph_verbose;
+   int graph_thresh;
 };
 
 struct filter_entry {
@@ -234,6 +235,9 @@ static int reset_tracing_files(struct perf_ftrace *ftrace 
__maybe_unused)
if (write_tracing_file("max_graph_depth", "0") < 0)
return -1;
 
+   if (write_tracing_file("tracing_thresh", "0") < 0)
+   return -1;
+
reset_tracing_filters();
reset_tracing_options(ftrace);
return 0;
@@ -446,6 +450,20 @@ static int set_tracing_funcgraph_verbose(struct 
perf_ftrace *ftrace)
return 0;
 }
 
+static int set_tracing_thresh(struct perf_ftrace *ftrace)
+{
+   int ret;
+
+   if (ftrace->graph_thresh == 0)
+   return 0;
+
+   ret = write_tracing_file_int("tracing_thresh", ftrace->graph_thresh);
+   if (ret < 0)
+   return ret;
+
+   return 0;
+}
+
 static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
**argv)
 {
char *trace_file;
@@ -545,6 +563,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
goto out_reset;
}
 
+   if (set_tracing_thresh(ftrace) < 0) {
+   pr_err("failed to set tracing thresh\n");
+   goto out_reset;
+   }
+
if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
goto out_reset;
@@ -727,6 +750,7 @@ static int parse_graph_tracer_opts(const struct option *opt,
{ .name = "nosleep-time",   .value_ptr = 
&ftrace->graph_nosleep_time },
{ .name = "noirqs", .value_ptr = 
&ftrace->graph_noirqs },
{ .name = "verbose",.value_ptr = 
&ftrace->graph_verbose },
+   { .name = "thresh", .value_ptr = 
&ftrace->graph_thresh },
{ .name = NULL, }
};
 
@@ -798,7 +822,7 @@ int cmd_ftrace(int argc, const char **argv)
OPT_INTEGER('D', "graph-depth", &ftrace.graph_depth,
"Max depth for function graph tracer"),
OPT_CALLBACK(0, "graph-opts", &ftrace, "options",
-"graph tracer options, available options: 
nosleep-time,noirqs,verbose",
+"graph tracer options, available options: 
nosleep-time,noirqs,verbose,thresh=",
 parse_graph_tracer_opts),
OPT_CALLBACK('m', "buffer-size", &ftrace.percpu_buffer_size, "size",
 "size of per cpu buffer", parse_buffer_size),
-- 
2.25.1



[PATCH v8 14/18] perf: ftrace: allow set graph depth by '--graph-opts'

2020-08-07 Thread Changbin Du
This is to have a consistent view of all graph tracer options.
The original option '--graph-depth' is marked as deprecated.

Signed-off-by: Changbin Du 
---
 tools/perf/Documentation/perf-ftrace.txt | 5 +
 tools/perf/builtin-ftrace.c  | 5 ++---
 2 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 6fa927e5971b..08216634d2bc 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -98,16 +98,13 @@ OPTIONS
specify multiple functions. It will be passed to 'set_graph_notrace'
in tracefs.
 
--D::
---graph-depth=::
-   Set max depth for function graph tracer to follow
-
 --graph-opts::
List of options allowed to set:
  nosleep-time - Measure on-CPU time only for function_graph tracer.
  noirqs   - Ignore functions that happen inside interrupt.
  verbose  - Show process names, PIDs, timestamps, etc.
  thresh=   - Setup trace duration threshold in microseconds.
+ depth=- Set max depth for function graph tracer to follow.
 
 SEE ALSO
 
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index ca61f8b8bbf6..bc3b35d18167 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -751,6 +751,7 @@ static int parse_graph_tracer_opts(const struct option *opt,
{ .name = "noirqs", .value_ptr = 
&ftrace->graph_noirqs },
{ .name = "verbose",.value_ptr = 
&ftrace->graph_verbose },
{ .name = "thresh", .value_ptr = 
&ftrace->graph_thresh },
+   { .name = "depth",  .value_ptr = 
&ftrace->graph_depth },
{ .name = NULL, }
};
 
@@ -819,10 +820,8 @@ int cmd_ftrace(int argc, const char **argv)
 parse_filter_func),
OPT_CALLBACK('g', "nograph-funcs", &ftrace.nograph_funcs, "func",
 "Set nograph filter on given functions", 
parse_filter_func),
-   OPT_INTEGER('D', "graph-depth", &ftrace.graph_depth,
-   "Max depth for function graph tracer"),
OPT_CALLBACK(0, "graph-opts", &ftrace, "options",
-"graph tracer options, available options: 
nosleep-time,noirqs,verbose,thresh=",
+"graph tracer options, available options: 
nosleep-time,noirqs,verbose,thresh=,depth=",
 parse_graph_tracer_opts),
OPT_CALLBACK('m', "buffer-size", &ftrace.percpu_buffer_size, "size",
 "size of per cpu buffer", parse_buffer_size),
-- 
2.25.1



[PATCH v8 11/18] perf ftrace: add support for tracing option 'irq-info'

2020-08-07 Thread Changbin Du
This adds support to display irq context info for function tracer. To do
this, just specify a '--func-opts irq-info' option.

Signed-off-by: Changbin Du 
---
 tools/perf/Documentation/perf-ftrace.txt |  1 +
 tools/perf/builtin-ftrace.c  | 21 -
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index fca55ac55ff3..37ea3ea97922 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -79,6 +79,7 @@ OPTIONS
 --func-opts::
List of options allowed to set:
  call-graph - Display kernel stack trace for function tracer.
+ irq-info   - Display irq context info for function tracer.
 
 -G::
 --graph-funcs=::
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index b4c821be4fb5..d1241febe143 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -44,6 +44,7 @@ struct perf_ftrace {
unsigned long   percpu_buffer_size;
boolinherit;
int func_stack_trace;
+   int func_irq_info;
int graph_nosleep_time;
int graph_noirqs;
 };
@@ -209,6 +210,7 @@ static void reset_tracing_options(struct perf_ftrace 
*ftrace __maybe_unused)
write_tracing_option_file("func_stack_trace", "0");
write_tracing_option_file("sleep-time", "1");
write_tracing_option_file("funcgraph-irqs", "1");
+   write_tracing_option_file("irq-info", "0");
 }
 
 static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
@@ -296,6 +298,17 @@ static int set_tracing_func_stack_trace(struct perf_ftrace 
*ftrace)
return 0;
 }
 
+static int set_tracing_func_irqinfo(struct perf_ftrace *ftrace)
+{
+   if (!ftrace->func_irq_info)
+   return 0;
+
+   if (write_tracing_option_file("irq-info", "1") < 0)
+   return -1;
+
+   return 0;
+}
+
 static int reset_tracing_cpu(void)
 {
struct perf_cpu_map *cpumap = perf_cpu_map__new(NULL);
@@ -471,6 +484,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
goto out_reset;
}
 
+   if (set_tracing_func_irqinfo(ftrace) < 0) {
+   pr_err("failed to set tracing option irq-info\n");
+   goto out_reset;
+   }
+
if (set_tracing_filters(ftrace) < 0) {
pr_err("failed to set tracing filters\n");
goto out_reset;
@@ -660,6 +678,7 @@ static int parse_func_tracer_opts(const struct option *opt,
struct perf_ftrace *ftrace = (struct perf_ftrace *) opt->value;
struct sublevel_option func_tracer_opts[] = {
{ .name = "call-graph", .value_ptr = &ftrace->func_stack_trace 
},
+   { .name = "irq-info",   .value_ptr = &ftrace->func_irq_info },
{ .name = NULL, }
};
 
@@ -742,7 +761,7 @@ int cmd_ftrace(int argc, const char **argv)
OPT_CALLBACK('N', "notrace-funcs", &ftrace.notrace, "func",
 "do not trace given functions", parse_filter_func),
OPT_CALLBACK(0, "func-opts", &ftrace, "options",
-"function tracer options, available options: call-graph",
+"function tracer options, available options: 
call-graph,irq-info",
 parse_func_tracer_opts),
OPT_CALLBACK('G', "graph-funcs", &ftrace.graph_funcs, "func",
 "trace given functions using function_graph tracer",
-- 
2.25.1



[PATCH v8 12/18] perf ftrace: add option 'verbose' to show more info for graph tracer

2020-08-07 Thread Changbin Du
Sometimes we want ftrace display more and longer information about
the trace.

$ sudo perf ftrace -G '*'
 2)   0.979 us|  mutex_unlock();
 2)   1.540 us|  __fsnotify_parent();
 2)   0.433 us|  fsnotify();

$ sudo perf ftrace -G '*' --graph-opts verbose
14160.770883 |   0)  <...>-47814   |   |   1.289 us|  mutex_unlock();
14160.770886 |   0)  <...>-47814   |   |   1.624 us|  
__fsnotify_parent();
14160.770887 |   0)  <...>-47814   |   |   0.636 us|  fsnotify();
14160.770888 |   0)  <...>-47814   |   |   0.328 us|  __sb_end_write();
14160.770888 |   0)  <...>-47814   |  d... |   0.430 us|  
fpregs_assert_state_consistent();
14160.770889 |   0)  <...>-47814   |  d... |   |  do_syscall_64() {
14160.770889 |   0)  <...>-47814   |  .... |       |
__x64_sys_close() {

Signed-off-by: Changbin Du 
---
 tools/perf/Documentation/perf-ftrace.txt |  1 +
 tools/perf/builtin-ftrace.c  | 29 +++-
 2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 37ea3ea97922..a2056aaf2ece 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -106,6 +106,7 @@ OPTIONS
List of options allowed to set:
  nosleep-time - Measure on-CPU time only for function_graph tracer.
  noirqs   - Ignore functions that happen inside interrupt.
+ verbose  - Show process names, PIDs, timestamps, etc.
 
 SEE ALSO
 
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index d1241febe143..8ee5287bd84a 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -47,6 +47,7 @@ struct perf_ftrace {
int func_irq_info;
int graph_nosleep_time;
int graph_noirqs;
+   int graph_verbose;
 };
 
 struct filter_entry {
@@ -210,6 +211,9 @@ static void reset_tracing_options(struct perf_ftrace 
*ftrace __maybe_unused)
write_tracing_option_file("func_stack_trace", "0");
write_tracing_option_file("sleep-time", "1");
write_tracing_option_file("funcgraph-irqs", "1");
+   write_tracing_option_file("funcgraph-proc", "0");
+   write_tracing_option_file("funcgraph-abstime", "0");
+   write_tracing_option_file("latency-format", "0");
write_tracing_option_file("irq-info", "0");
 }
 
@@ -425,6 +429,23 @@ static int set_tracing_funcgraph_irqs(struct perf_ftrace 
*ftrace)
return 0;
 }
 
+static int set_tracing_funcgraph_verbose(struct perf_ftrace *ftrace)
+{
+   if (!ftrace->graph_verbose)
+   return 0;
+
+   if (write_tracing_option_file("funcgraph-proc", "1") < 0)
+   return -1;
+
+   if (write_tracing_option_file("funcgraph-abstime", "1") < 0)
+   return -1;
+
+   if (write_tracing_option_file("latency-format", "1") < 0)
+   return -1;
+
+   return 0;
+}
+
 static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
**argv)
 {
char *trace_file;
@@ -519,6 +540,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
goto out_reset;
}
 
+   if (set_tracing_funcgraph_verbose(ftrace) < 0) {
+   pr_err("failed to set tracing option 
funcgraph-proc/funcgraph-abstime\n");
+   goto out_reset;
+   }
+
if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
goto out_reset;
@@ -700,6 +726,7 @@ static int parse_graph_tracer_opts(const struct option *opt,
struct sublevel_option graph_tracer_opts[] = {
{ .name = "nosleep-time",   .value_ptr = 
&ftrace->graph_nosleep_time },
{ .name = "noirqs", .value_ptr = 
&ftrace->graph_noirqs },
+   { .name = "verbose",.value_ptr = 
&ftrace->graph_verbose },
{ .name = NULL, }
};
 
@@ -771,7 +798,7 @@ int cmd_ftrace(int argc, const char **argv)
OPT_INTEGER('D', "graph-depth", &ftrace.graph_depth,
"Max depth for function graph tracer"),
OPT_CALLBACK(0, "graph-opts", &ftrace, "options",
-"graph tracer options, available options: 
nosleep-time,noirqs",
+"graph tracer options, available options: 
nosleep-time,noirqs,verbose",
 parse_graph_tracer_opts),
OPT_CALLBACK('m', "buffer-size", &ftrace.percpu_buffer_size, "size",
 "size of per cpu buffer", parse_buffer_size),
-- 
2.25.1



[PATCH v8 07/18] perf: util: add general function to parse sublevel options

2020-08-07 Thread Changbin Du
This factors out a general function perf_parse_sublevel_options() to parse
sublevel options. The 'sublevel' options is something like the '--debug'
options which allow more sublevel options.

Signed-off-by: Changbin Du 

---
v2: add util/parse-sublevel-options.c
---
 tools/perf/util/Build|  1 +
 tools/perf/util/debug.c  | 61 ++---
 tools/perf/util/parse-sublevel-options.c | 70 
 tools/perf/util/parse-sublevel-options.h | 11 
 4 files changed, 99 insertions(+), 44 deletions(-)
 create mode 100644 tools/perf/util/parse-sublevel-options.c
 create mode 100644 tools/perf/util/parse-sublevel-options.h

diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 8d18380ecd10..e86607ada0b5 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -117,6 +117,7 @@ endif
 perf-y += parse-branch-options.o
 perf-y += dump-insn.o
 perf-y += parse-regs-options.o
+perf-y += parse-sublevel-options.o
 perf-y += term.o
 perf-y += help-unknown-cmd.o
 perf-y += mem-events.o
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index adb656745ecc..5cda5565777a 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -20,6 +20,7 @@
 #include "target.h"
 #include "ui/helpline.h"
 #include "ui/ui.h"
+#include "util/parse-sublevel-options.h"
 
 #include 
 
@@ -173,65 +174,37 @@ void trace_event(union perf_event *event)
 trace_event_printer, event);
 }
 
-static struct debug_variable {
-   const char *name;
-   int *ptr;
-} debug_variables[] = {
-   { .name = "verbose",.ptr = &verbose },
-   { .name = "ordered-events", .ptr = &debug_ordered_events},
-   { .name = "stderr", .ptr = &redirect_to_stderr},
-   { .name = "data-convert",   .ptr = &debug_data_convert },
-   { .name = "perf-event-open",.ptr = &debug_peo_args },
+static struct sublevel_option debug_opts[] = {
+   { .name = "verbose",.value_ptr = &verbose },
+   { .name = "ordered-events", .value_ptr = &debug_ordered_events},
+   { .name = "stderr", .value_ptr = &redirect_to_stderr},
+   { .name = "data-convert",   .value_ptr = &debug_data_convert },
+   { .name = "perf-event-open",.value_ptr = &debug_peo_args },
{ .name = NULL, }
 };
 
 int perf_debug_option(const char *str)
 {
-   struct debug_variable *var = &debug_variables[0];
-   char *vstr, *s = strdup(str);
-   int v = 1;
-
-   vstr = strchr(s, '=');
-   if (vstr)
-   *vstr++ = 0;
-
-   while (var->name) {
-   if (!strcmp(s, var->name))
-   break;
-   var++;
-   }
-
-   if (!var->name) {
-   pr_err("Unknown debug variable name '%s'\n", s);
-   free(s);
-   return -1;
-   }
+   int ret;
 
-   if (vstr) {
-   v = atoi(vstr);
-   /*
-* Allow only values in range (0, 10),
-* otherwise set 0.
-*/
-   v = (v < 0) || (v > 10) ? 0 : v;
-   }
+   ret = perf_parse_sublevel_options(str, debug_opts);
+   if (ret)
+   return ret;
 
-   if (quiet)
-   v = -1;
+   /* Allow only verbose value in range (0, 10), otherwise set 0. */
+   verbose = (verbose < 0) || (verbose > 10) ? 0 : verbose;
 
-   *var->ptr = v;
-   free(s);
return 0;
 }
 
 int perf_quiet_option(void)
 {
-   struct debug_variable *var = &debug_variables[0];
+   struct sublevel_option *opt = &debug_opts[0];
 
/* disable all debug messages */
-   while (var->name) {
-   *var->ptr = -1;
-   var++;
+   while (opt->name) {
+   *opt->value_ptr = -1;
+   opt++;
}
 
return 0;
diff --git a/tools/perf/util/parse-sublevel-options.c 
b/tools/perf/util/parse-sublevel-options.c
new file mode 100644
index ..a841d17ffd57
--- /dev/null
+++ b/tools/perf/util/parse-sublevel-options.c
@@ -0,0 +1,70 @@
+#include 
+#include 
+#include 
+#include 
+
+#include "util/debug.h"
+#include "util/parse-sublevel-options.h"
+
+static int parse_one_sublevel_option(const char *str,
+struct sublevel_option *opts)
+{
+   struct sublevel_option *opt = opts;
+   char *vstr, *s = strdup(str);
+   int v = 1;
+
+   if (!s) {
+   pr_err("no memory\n");
+   return -1;
+   }
+
+   vstr = strchr(s, '=');
+   if (vstr)
+   *vstr++ = 0;
+
+   while (opt->name) {

[PATCH v8 10/18] perf ftrace: add support for trace option funcgraph-irqs

2020-08-07 Thread Changbin Du
This adds an option '--graph-opts noirqs' to filter out functions executed
in irq context.

Signed-off-by: Changbin Du 

---
v2: option name '--nofuncgraph-irqs' -> '--graph-noirqs'.
---
 tools/perf/Documentation/perf-ftrace.txt |  1 +
 tools/perf/builtin-ftrace.c  | 21 -
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 3380a2e2c9ad..fca55ac55ff3 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -104,6 +104,7 @@ OPTIONS
 --graph-opts::
List of options allowed to set:
  nosleep-time - Measure on-CPU time only for function_graph tracer.
+ noirqs   - Ignore functions that happen inside interrupt.
 
 SEE ALSO
 
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 47d63bba6a48..b4c821be4fb5 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -45,6 +45,7 @@ struct perf_ftrace {
boolinherit;
int func_stack_trace;
int graph_nosleep_time;
+   int graph_noirqs;
 };
 
 struct filter_entry {
@@ -207,6 +208,7 @@ static void reset_tracing_options(struct perf_ftrace 
*ftrace __maybe_unused)
write_tracing_option_file("function-fork", "0");
write_tracing_option_file("func_stack_trace", "0");
write_tracing_option_file("sleep-time", "1");
+   write_tracing_option_file("funcgraph-irqs", "1");
 }
 
 static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
@@ -399,6 +401,17 @@ static int set_tracing_sleep_time(struct perf_ftrace 
*ftrace)
return 0;
 }
 
+static int set_tracing_funcgraph_irqs(struct perf_ftrace *ftrace)
+{
+   if (!ftrace->graph_noirqs)
+   return 0;
+
+   if (write_tracing_option_file("funcgraph-irqs", "0") < 0)
+   return -1;
+
+   return 0;
+}
+
 static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
**argv)
 {
char *trace_file;
@@ -483,6 +496,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
goto out_reset;
}
 
+   if (set_tracing_funcgraph_irqs(ftrace) < 0) {
+   pr_err("failed to set tracing option funcgraph-irqs\n");
+   goto out_reset;
+   }
+
if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
goto out_reset;
@@ -662,6 +680,7 @@ static int parse_graph_tracer_opts(const struct option *opt,
struct perf_ftrace *ftrace = (struct perf_ftrace *) opt->value;
struct sublevel_option graph_tracer_opts[] = {
{ .name = "nosleep-time",   .value_ptr = 
&ftrace->graph_nosleep_time },
+   { .name = "noirqs", .value_ptr = 
&ftrace->graph_noirqs },
{ .name = NULL, }
};
 
@@ -733,7 +752,7 @@ int cmd_ftrace(int argc, const char **argv)
OPT_INTEGER('D', "graph-depth", &ftrace.graph_depth,
"Max depth for function graph tracer"),
OPT_CALLBACK(0, "graph-opts", &ftrace, "options",
-"graph tracer options, available options: nosleep-time",
+"graph tracer options, available options: 
nosleep-time,noirqs",
 parse_graph_tracer_opts),
OPT_CALLBACK('m', "buffer-size", &ftrace.percpu_buffer_size, "size",
 "size of per cpu buffer", parse_buffer_size),
-- 
2.25.1



[PATCH v8 08/18] perf ftrace: add support for tracing option 'func_stack_trace'

2020-08-07 Thread Changbin Du
This adds support to display call trace for function tracer. To do this,
just specify a '--func-opts call-graph' option.

$ sudo perf ftrace -T vfs_read --func-opts call-graph
 iio-sensor-prox-855   [003]   6168.369657: vfs_read <-ksys_read
 iio-sensor-prox-855   [003]   6168.369677: 
 => vfs_read
 => ksys_read
 => __x64_sys_read
 => do_syscall_64
 => entry_SYSCALL_64_after_hwframe
 ...

Signed-off-by: Changbin Du 

---
v3: switch to uniform option --func-opts.
v2: option name '-s' -> '--func-call-graph'
---
 tools/perf/Documentation/perf-ftrace.txt |  4 +++
 tools/perf/builtin-ftrace.c  | 42 
 2 files changed, 46 insertions(+)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index c46d0a09b38c..8f08ad0992c2 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -76,6 +76,10 @@ OPTIONS
specify multiple functions (or glob patterns).  It will be
passed to 'set_ftrace_notrace' in tracefs.
 
+--func-opts::
+   List of options allowed to set:
+ call-graph - Display kernel stack trace for function tracer.
+
 -G::
 --graph-funcs=::
Select function_graph tracer and set graph filter on the given
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 07b81d0c1658..469b89748c42 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -27,6 +27,7 @@
 #include "util/cap.h"
 #include "util/config.h"
 #include "util/units.h"
+#include "util/parse-sublevel-options.h"
 
 #define DEFAULT_TRACER  "function_graph"
 
@@ -42,6 +43,7 @@ struct perf_ftrace {
int graph_depth;
unsigned long   percpu_buffer_size;
boolinherit;
+   int func_stack_trace;
 };
 
 struct filter_entry {
@@ -202,6 +204,7 @@ static void reset_tracing_filters(void);
 static void reset_tracing_options(struct perf_ftrace *ftrace __maybe_unused)
 {
write_tracing_option_file("function-fork", "0");
+   write_tracing_option_file("func_stack_trace", "0");
 }
 
 static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
@@ -278,6 +281,17 @@ static int set_tracing_cpu(struct perf_ftrace *ftrace)
return set_tracing_cpumask(cpumap);
 }
 
+static int set_tracing_func_stack_trace(struct perf_ftrace *ftrace)
+{
+   if (!ftrace->func_stack_trace)
+   return 0;
+
+   if (write_tracing_option_file("func_stack_trace", "1") < 0)
+   return -1;
+
+   return 0;
+}
+
 static int reset_tracing_cpu(void)
 {
struct perf_cpu_map *cpumap = perf_cpu_map__new(NULL);
@@ -426,6 +440,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
goto out_reset;
}
 
+   if (set_tracing_func_stack_trace(ftrace) < 0) {
+   pr_err("failed to set tracing option func_stack_trace\n");
+   goto out_reset;
+   }
+
if (set_tracing_filters(ftrace) < 0) {
pr_err("failed to set tracing filters\n");
goto out_reset;
@@ -598,6 +617,26 @@ static int parse_buffer_size(const struct option *opt,
return -1;
 }
 
+static int parse_func_tracer_opts(const struct option *opt,
+ const char *str, int unset)
+{
+   int ret;
+   struct perf_ftrace *ftrace = (struct perf_ftrace *) opt->value;
+   struct sublevel_option func_tracer_opts[] = {
+   { .name = "call-graph", .value_ptr = &ftrace->func_stack_trace 
},
+   { .name = NULL, }
+   };
+
+   if (unset)
+   return 0;
+
+   ret = perf_parse_sublevel_options(str, func_tracer_opts);
+   if (ret)
+   return ret;
+
+   return 0;
+}
+
 static void select_tracer(struct perf_ftrace *ftrace)
 {
bool graph = !list_empty(&ftrace->graph_funcs) ||
@@ -645,6 +684,9 @@ int cmd_ftrace(int argc, const char **argv)
 parse_filter_func),
OPT_CALLBACK('N', "notrace-funcs", &ftrace.notrace, "func",
 "do not trace given functions", parse_filter_func),
+   OPT_CALLBACK(0, "func-opts", &ftrace, "options",
+"function tracer options, available options: call-graph",
+parse_func_tracer_opts),
OPT_CALLBACK('G', "graph-funcs", &ftrace.graph_funcs, "func",
 "trace given functions using function_graph tracer",
 parse_filter_func),
-- 
2.25.1



[PATCH v8 16/18] perf ftrace: add option --tid to filter by thread id

2020-08-07 Thread Changbin Du
This allows us to trace single thread instead of the whole process.

Signed-off-by: Changbin Du 
---
 tools/perf/Documentation/perf-ftrace.txt | 3 +++
 tools/perf/builtin-ftrace.c  | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 29c684b3b3fd..78358af9a1c4 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -39,6 +39,9 @@ OPTIONS
 --pid=::
Trace on existing process id (comma separated list).
 
+--tid=::
+   Trace on existing thread id (comma separated list).
+
 -D::
 --delay::
Time (ms) to wait before starting tracing after program start.
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 5f9a9ebea0a2..13abb737fd12 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -812,6 +812,9 @@ int cmd_ftrace(int argc, const char **argv)
"Show available functions to filter"),
OPT_STRING('p', "pid", &ftrace.target.pid, "pid",
   "trace on existing process id"),
+   /* TODO: Add short option -t after -t/--tracer can be removed. */
+   OPT_STRING(0, "tid", &ftrace.target.tid, "tid",
+  "trace on existing thread id (exclusive to --pid)"),
OPT_INCR('v', "verbose", &verbose,
 "be more verbose"),
OPT_BOOLEAN('a', "all-cpus", &ftrace.target.system_wide,
-- 
2.25.1



[PATCH v8 06/18] perf ftrace: add option '--inherit' to trace children processes

2020-08-07 Thread Changbin Du
This adds an option '--inherit' to allow us trace children
processes spawned by our target.

Signed-off-by: Changbin Du 

---
v2: option name '--trace-children' -> '--inherit'.
---
 tools/perf/Documentation/perf-ftrace.txt |  3 ++
 tools/perf/builtin-ftrace.c  | 38 
 2 files changed, 41 insertions(+)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 7a5d915f60b0..c46d0a09b38c 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -58,6 +58,9 @@ OPTIONS
Set the size of per-cpu tracing buffer,  is expected to
be a number with appended unit character - B/K/M/G.
 
+--inherit::
+   Trace children processes spawned by our target.
+
 -T::
 --trace-funcs=::
Select function tracer and set function filter on the given
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 39c694be2b71..07b81d0c1658 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -41,6 +41,7 @@ struct perf_ftrace {
struct list_headnograph_funcs;
int graph_depth;
unsigned long   percpu_buffer_size;
+   boolinherit;
 };
 
 struct filter_entry {
@@ -182,9 +183,27 @@ static int write_tracing_file_int(const char *name, int 
value)
return 0;
 }
 
+static int write_tracing_option_file(const char *name, const char *val)
+{
+   char *file;
+   int ret;
+
+   if (asprintf(&file, "options/%s", name) < 0)
+   return -1;
+
+   ret = __write_tracing_file(file, val, false);
+   free(file);
+   return ret;
+}
+
 static int reset_tracing_cpu(void);
 static void reset_tracing_filters(void);
 
+static void reset_tracing_options(struct perf_ftrace *ftrace __maybe_unused)
+{
+   write_tracing_option_file("function-fork", "0");
+}
+
 static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
 {
if (write_tracing_file("tracing_on", "0") < 0)
@@ -203,6 +222,7 @@ static int reset_tracing_files(struct perf_ftrace *ftrace 
__maybe_unused)
return -1;
 
reset_tracing_filters();
+   reset_tracing_options(ftrace);
return 0;
 }
 
@@ -341,6 +361,17 @@ static int set_tracing_percpu_buffer_size(struct 
perf_ftrace *ftrace)
return 0;
 }
 
+static int set_tracing_trace_inherit(struct perf_ftrace *ftrace)
+{
+   if (!ftrace->inherit)
+   return 0;
+
+   if (write_tracing_option_file("function-fork", "1") < 0)
+   return -1;
+
+   return 0;
+}
+
 static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
**argv)
 {
char *trace_file;
@@ -410,6 +441,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
goto out_reset;
}
 
+   if (set_tracing_trace_inherit(ftrace) < 0) {
+   pr_err("failed to set tracing option function-fork\n");
+   goto out_reset;
+   }
+
if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
goto out_reset;
@@ -618,6 +654,8 @@ int cmd_ftrace(int argc, const char **argv)
"Max depth for function graph tracer"),
OPT_CALLBACK('m', "buffer-size", &ftrace.percpu_buffer_size, "size",
 "size of per cpu buffer", parse_buffer_size),
+   OPT_BOOLEAN(0, "inherit", &ftrace.inherit,
+   "trace children processes"),
OPT_END()
};
 
-- 
2.25.1



[PATCH v8 04/18] perf ftrace: add option '-m/--buffer-size' to set per-cpu buffer size

2020-08-07 Thread Changbin Du
This adds an option '-m/--buffer-size' to allow us set the size of per-cpu
tracing buffer.

Signed-off-by: Changbin Du 

---
v2: support units as a suffix.
---
 tools/perf/Documentation/perf-ftrace.txt |  5 +++
 tools/perf/builtin-ftrace.c  | 55 
 2 files changed, 60 insertions(+)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 4f5628445a63..7a5d915f60b0 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -53,6 +53,11 @@ OPTIONS
Ranges of CPUs are specified with -: 0-2.
Default is to trace on all online CPUs.
 
+-m::
+--buffer-size::
+   Set the size of per-cpu tracing buffer,  is expected to
+   be a number with appended unit character - B/K/M/G.
+
 -T::
 --trace-funcs=::
Select function tracer and set function filter on the given
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 4b3fcee5725a..a3a4f4be9dde 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -26,6 +26,7 @@
 #include "thread_map.h"
 #include "util/cap.h"
 #include "util/config.h"
+#include "util/units.h"
 
 #define DEFAULT_TRACER  "function_graph"
 
@@ -39,6 +40,7 @@ struct perf_ftrace {
struct list_headgraph_funcs;
struct list_headnograph_funcs;
int graph_depth;
+   unsigned long   percpu_buffer_size;
 };
 
 struct filter_entry {
@@ -324,6 +326,21 @@ static int set_tracing_depth(struct perf_ftrace *ftrace)
return 0;
 }
 
+static int set_tracing_percpu_buffer_size(struct perf_ftrace *ftrace)
+{
+   int ret;
+
+   if (ftrace->percpu_buffer_size == 0)
+   return 0;
+
+   ret = write_tracing_file_int("buffer_size_kb",
+ftrace->percpu_buffer_size / 1024);
+   if (ret < 0)
+   return ret;
+
+   return 0;
+}
+
 static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
**argv)
 {
char *trace_file;
@@ -388,6 +405,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
goto out_reset;
}
 
+   if (set_tracing_percpu_buffer_size(ftrace) < 0) {
+   pr_err("failed to set tracing per-cpu buffer size\n");
+   goto out_reset;
+   }
+
if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
goto out_reset;
@@ -506,6 +528,37 @@ static void delete_filter_func(struct list_head *head)
}
 }
 
+static int parse_buffer_size(const struct option *opt,
+const char *str, int unset)
+{
+   unsigned long *s = (unsigned long *)opt->value;
+   static struct parse_tag tags_size[] = {
+   { .tag  = 'B', .mult = 1   },
+   { .tag  = 'K', .mult = 1 << 10 },
+   { .tag  = 'M', .mult = 1 << 20 },
+   { .tag  = 'G', .mult = 1 << 30 },
+   { .tag  = 0 },
+   };
+   unsigned long val;
+
+   if (unset) {
+   *s = 0;
+   return 0;
+   }
+
+   val = parse_tag_value(str, tags_size);
+   if (val != (unsigned long) -1) {
+   if (val < 1024) {
+   pr_err("buffer size too small, must larger than 1KB.");
+   return -1;
+   }
+   *s = val;
+   return 0;
+   }
+
+   return -1;
+}
+
 static void select_tracer(struct perf_ftrace *ftrace)
 {
bool graph = !list_empty(&ftrace->graph_funcs) ||
@@ -560,6 +613,8 @@ int cmd_ftrace(int argc, const char **argv)
 "Set nograph filter on given functions", 
parse_filter_func),
OPT_INTEGER('D', "graph-depth", &ftrace.graph_depth,
"Max depth for function graph tracer"),
+   OPT_CALLBACK('m', "buffer-size", &ftrace.percpu_buffer_size, "size",
+"size of per cpu buffer", parse_buffer_size),
OPT_END()
};
 
-- 
2.25.1



[PATCH v8 03/18] perf ftrace: factor out function write_tracing_file_int()

2020-08-07 Thread Changbin Du
We will reuse this function later.

Signed-off-by: Changbin Du 
---
 tools/perf/builtin-ftrace.c | 17 -
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 1ebf71ecc1a8..4b3fcee5725a 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -169,6 +169,17 @@ static int read_tracing_file_to_stdout(const char *name)
return ret;
 }
 
+static int write_tracing_file_int(const char *name, int value)
+{
+   char buf[16];
+
+   snprintf(buf, sizeof(buf), "%d", value);
+   if (write_tracing_file(name, buf) < 0)
+   return -1;
+
+   return 0;
+}
+
 static int reset_tracing_cpu(void);
 static void reset_tracing_filters(void);
 
@@ -299,8 +310,6 @@ static void reset_tracing_filters(void)
 
 static int set_tracing_depth(struct perf_ftrace *ftrace)
 {
-   char buf[16];
-
if (ftrace->graph_depth == 0)
return 0;
 
@@ -309,9 +318,7 @@ static int set_tracing_depth(struct perf_ftrace *ftrace)
return -1;
}
 
-   snprintf(buf, sizeof(buf), "%d", ftrace->graph_depth);
-
-   if (write_tracing_file("max_graph_depth", buf) < 0)
+   if (write_tracing_file_int("max_graph_depth", ftrace->graph_depth) < 0)
return -1;
 
return 0;
-- 
2.25.1



[PATCH v8 05/18] perf ftrace: show trace column header

2020-08-07 Thread Changbin Du
This makes perf-ftrace display column header before printing trace.

  $ sudo perf ftrace
  # tracer: function
  #
  # entries-in-buffer/entries-written: 0/0   #P:8
  #
  #TASK-PID CPU#   TIMESTAMP  FUNCTION
  #  | | |   | |
 <...>-9246  [006]  10726.262760: mutex_unlock <-rb_simple_write
 <...>-9246  [006]  10726.262764: __fsnotify_parent <-vfs_write
 <...>-9246  [006]  10726.262765: fsnotify <-vfs_write
 <...>-9246  [006]  10726.262766: __sb_end_write <-vfs_write
 <...>-9246  [006]  10726.262767: fpregs_assert_state_consistent 
<-do_syscall_64

Signed-off-by: Changbin Du 
---
 tools/perf/builtin-ftrace.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index a3a4f4be9dde..39c694be2b71 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -435,6 +435,9 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
fcntl(trace_fd, F_SETFL, O_NONBLOCK);
pollfd.fd = trace_fd;
 
+   /* display column headers */
+   read_tracing_file_to_stdout("trace");
+
if (write_tracing_file("tracing_on", "1") < 0) {
pr_err("can't enable tracing\n");
goto out_close_fd;
-- 
2.25.1



[PATCH v8 01/18] perf ftrace: select function/function_graph tracer automatically

2020-08-07 Thread Changbin Du
The '-g/-G' options have already implied function_graph tracer should be
used instead of function tracer. So we don't need extra option '--tracer'
in this case.

This patch changes the behavior as below:
  - If '-g' or '-G' option is on, then function_graph tracer is used.
  - If '-T' or '-N' option is on, then function tracer is used.
  - The function_graph has priority over function tracer.
  - The option '--tracer' only take effect if neither -g/-G nor -T/-N
is specified.

Here are some examples.

This will start tracing all functions using default tracer:
  $ sudo perf ftrace

This will trace all functions using function graph tracer:
  $ sudo perf ftrace -G '*'

This will trace function vfs_read using function graph tracer:
  $ sudo perf ftrace -G vfs_read

This will trace function vfs_read using function tracer:
  $ sudo perf ftrace -T vfs_read

Signed-off-by: Changbin Du 

---
v4: changed tracer selection policy.
v3: remove default '*' for -G/-T.
---
 tools/perf/Documentation/perf-config.txt |  5 +--
 tools/perf/Documentation/perf-ftrace.txt | 41 +---
 tools/perf/builtin-ftrace.c  | 25 +--
 3 files changed, 48 insertions(+), 23 deletions(-)

diff --git a/tools/perf/Documentation/perf-config.txt 
b/tools/perf/Documentation/perf-config.txt
index c7d3df5798e2..76408d986aed 100644
--- a/tools/perf/Documentation/perf-config.txt
+++ b/tools/perf/Documentation/perf-config.txt
@@ -614,8 +614,9 @@ trace.*::
 
 ftrace.*::
ftrace.tracer::
-   Can be used to select the default tracer. Possible values are
-   'function' and 'function_graph'.
+   Can be used to select the default tracer when neither -G nor
+   -F option is not specified. Possible values are 'function' and
+   'function_graph'.
 
 llvm.*::
llvm.clang-path::
diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index b80c84307dc9..821d4d334a09 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -24,7 +24,8 @@ OPTIONS
 
 -t::
 --tracer=::
-   Tracer to use: function_graph or function.
+   Tracer to use when neither -G nor -F option is not
+   specified: function_graph or function.
 
 -v::
 --verbose=::
@@ -50,33 +51,35 @@ OPTIONS
 
 -T::
 --trace-funcs=::
-   Only trace functions given by the argument.  Multiple functions
-   can be given by using this option more than once.  The function
-   argument also can be a glob pattern.  It will be passed to
-   'set_ftrace_filter' in tracefs.
+   Select function tracer and set function filter on the given
+   function (or a glob pattern). Multiple functions can be given
+   by using this option more than once. The function argument also
+   can be a glob pattern. It will be passed to 'set_ftrace_filter'
+   in tracefs.
 
 -N::
 --notrace-funcs=::
-   Do not trace functions given by the argument.  Like -T option,
-   this can be used more than once to specify multiple functions
-   (or glob patterns).  It will be passed to 'set_ftrace_notrace'
-   in tracefs.
+   Select function tracer and do not trace functions given by the
+   argument.  Like -T option, this can be used more than once to
+   specify multiple functions (or glob patterns).  It will be
+   passed to 'set_ftrace_notrace' in tracefs.
 
 -G::
 --graph-funcs=::
-   Set graph filter on the given function (or a glob pattern).
-   This is useful for the function_graph tracer only and enables
-   tracing for functions executed from the given function.
-   This can be used more than once to specify multiple functions.
-   It will be passed to 'set_graph_function' in tracefs.
+   Select function_graph tracer and set graph filter on the given
+   function (or a glob pattern). This is useful to trace for
+   functions executed from the given function. This can be used more
+   than once to specify multiple functions. It will be passed to
+   'set_graph_function' in tracefs.
 
 -g::
 --nograph-funcs=::
-   Set graph notrace filter on the given function (or a glob pattern).
-   Like -G option, this is useful for the function_graph tracer only
-   and disables tracing for function executed from the given function.
-   This can be used more than once to specify multiple functions.
-   It will be passed to 'set_graph_notrace' in tracefs.
+   Select function_graph tracer and set graph notrace filter on the
+   given function (or a glob pattern). Like -G option, this is useful
+   for the function_graph tracer only and disables tracing for function
+   executed from the given function. T

[PATCH v8 00/18] [PATCH v7 00/18] perf: ftrace enhancement

2020-08-07 Thread Changbin Du
The perf has basic kernel ftrace support but lack support of most tracing
options. This serias is target to enhance the perf ftrace functionality so
that we can make full use of kernel ftrace with perf.

In general, this serias be cataloged into two main changes:
  1) Improve usability of existing functions. For example, we don't need to type
 extra option to select the tracer.
  2) Add new options to support all other ftrace functions.

Here is a glance of all ftrace functions with this serias:

$ sudo perf ftrace -h

 Usage: perf ftrace [] []
or: perf ftrace [] --  []

-a, --all-cpussystem-wide collection from all CPUs
-C, --cpulist of cpus to monitor
-D, --delayms to wait before starting tracing after program start
-F, --funcs   Show available functions to filter
-G, --graph-funcs 
  trace given functions using function_graph tracer
-g, --nograph-funcs 
  Set nograph filter on given functions
-m, --buffer-size 
  size of per cpu buffer
-N, --notrace-funcs 
  do not trace given functions
-p, --pidtrace on existing process id
-T, --trace-funcs 
  trace given functions using function tracer
-t, --tracer 
  tracer to use: function_graph(default) or function
-v, --verbose be more verbose
--func-opts 
  function tracer options, available options: 
call-graph,irq-info
--graph-opts 
  graph tracer options, available options: 
nosleep-time,noirqs,verbose,thresh=,depth=
--inherit trace children processes
--tidtrace on existing thread id (exclusive to --pid)

v8:
  o change tracer selection policy ([PATCH 01/18]).
v7:
  o add back '--tid '.
v6:
  o fix return value of read_tracing_file_to_stdout().
  o make __cmd_ftrace() shorter.
  o remove option '-t, --tid '.
v5:
  o trivial fixes.
v4:
  o add util/parse-sublevel-options.c
  O remove -D/--graph-depth
v3:
  o add --func-opts and --graph-opts to set tracer specific options.
  o support units as a suffix for option '-m/--buffer-size'.
v2:
  o patches for option '-u/--userstacktrace' and '--no-pager' are dropped.
  o update all related perf documentation.
  o rename some options. Now all funcgraph tracer options are prefixed with
'--graph-', while all function tracer options are prefixed with '--func-'.
  o mark old options deprecated instead of removing them.

Acked-by: Namhyung Kim 

Changbin Du (18):
  perf ftrace: select function/function_graph tracer automatically
  perf ftrace: add option '-F/--funcs' to list available functions
  perf ftrace: factor out function write_tracing_file_int()
  perf ftrace: add option '-m/--buffer-size' to set per-cpu buffer size
  perf ftrace: show trace column header
  perf ftrace: add option '--inherit' to trace children processes
  perf: util: add general function to parse sublevel options
  perf ftrace: add support for tracing option 'func_stack_trace'
  perf ftrace: add support for trace option sleep-time
  perf ftrace: add support for trace option funcgraph-irqs
  perf ftrace: add support for tracing option 'irq-info'
  perf ftrace: add option 'verbose' to show more info for graph tracer
  perf ftrace: add support for trace option tracing_thresh
  perf: ftrace: allow set graph depth by '--graph-opts'
  perf ftrace: add option -D/--delay to delay tracing
  perf ftrace: add option --tid to filter by thread id
  perf: ftrace: Add set_tracing_options() to set all trace options
  perf ftrace: add change log

 tools/perf/Documentation/perf-config.txt |   5 +-
 tools/perf/Documentation/perf-ftrace.txt |  75 ++--
 tools/perf/builtin-ftrace.c  | 424 +--
 tools/perf/util/Build|   1 +
 tools/perf/util/debug.c  |  61 +---
 tools/perf/util/parse-sublevel-options.c |  70 
 tools/perf/util/parse-sublevel-options.h |  11 +
 7 files changed, 550 insertions(+), 97 deletions(-)
 create mode 100644 tools/perf/util/parse-sublevel-options.c
 create mode 100644 tools/perf/util/parse-sublevel-options.h

-- 
2.25.1



[PATCH v8 02/18] perf ftrace: add option '-F/--funcs' to list available functions

2020-08-07 Thread Changbin Du
This adds an option '-F/--funcs' to list all available functions to trace,
which is read from tracing file 'available_filter_functions'.

$ sudo ./perf ftrace -F | head
trace_initcall_finish_cb
initcall_blacklisted
do_one_initcall
do_one_initcall
trace_initcall_start_cb
run_init_process
try_to_run_init_process
match_dev_by_label
match_dev_by_uuid
rootfs_init_fs_context

Signed-off-by: Changbin Du 

---
v3: fix return value issue.
v2: option name '-l/--list-functions' -> '-F/--funcs'
---
 tools/perf/Documentation/perf-ftrace.txt |  4 +++
 tools/perf/builtin-ftrace.c  | 46 
 2 files changed, 50 insertions(+)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 821d4d334a09..4f5628445a63 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -31,6 +31,10 @@ OPTIONS
 --verbose=::
 Verbosity level.
 
+-F::
+--funcs::
+List all available functions to trace.
+
 -p::
 --pid=::
Trace on existing process id (comma separated list).
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 048a11192b59..1ebf71ecc1a8 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -33,6 +33,7 @@ struct perf_ftrace {
struct evlist   *evlist;
struct target   target;
const char  *tracer;
+   boollist_avail_functions;
struct list_headfilters;
struct list_headnotrace;
struct list_headgraph_funcs;
@@ -128,6 +129,46 @@ static int append_tracing_file(const char *name, const 
char *val)
return __write_tracing_file(name, val, true);
 }
 
+static int read_tracing_file_to_stdout(const char *name)
+{
+   char buf[4096];
+   char *file;
+   int fd;
+   int ret = -1;
+
+   file = get_tracing_file(name);
+   if (!file) {
+   pr_debug("cannot get tracing file: %s\n", name);
+   return -1;
+   }
+
+   fd = open(file, O_RDONLY);
+   if (fd < 0) {
+   pr_debug("cannot open tracing file: %s: %s\n",
+name, str_error_r(errno, buf, sizeof(buf)));
+   goto out;
+   }
+
+   /* read contents to stdout */
+   while (true) {
+   int n = read(fd, buf, sizeof(buf));
+   if (n == 0)
+   break;
+   else if (n < 0)
+   goto out_close;
+
+   if (fwrite(buf, n, 1, stdout) != 1)
+   goto out_close;
+   }
+   ret = 0;
+
+out_close:
+   close(fd);
+out:
+   put_tracing_file(file);
+   return ret;
+}
+
 static int reset_tracing_cpu(void);
 static void reset_tracing_filters(void);
 
@@ -302,6 +343,9 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
signal(SIGCHLD, sig_handler);
signal(SIGPIPE, sig_handler);
 
+   if (ftrace->list_avail_functions)
+   return 
read_tracing_file_to_stdout("available_filter_functions");
+
if (reset_tracing_files(ftrace) < 0) {
pr_err("failed to reset ftrace\n");
goto out;
@@ -487,6 +531,8 @@ int cmd_ftrace(int argc, const char **argv)
const struct option ftrace_options[] = {
OPT_STRING('t', "tracer", &ftrace.tracer, "tracer",
   "tracer to use: function_graph(default) or function"),
+   OPT_BOOLEAN('F', "funcs", &ftrace.list_avail_functions,
+   "Show available functions to filter"),
OPT_STRING('p', "pid", &ftrace.target.pid, "pid",
   "trace on existing process id"),
OPT_INCR('v', "verbose", &verbose,
-- 
2.25.1



Re: [PATCH v7 01/18] perf ftrace: select function/function_graph tracer automatically

2020-08-07 Thread Changbin Du
On Wed, Aug 05, 2020 at 10:05:03PM -0300, Arnaldo Carvalho de Melo wrote:
> 
> 
> On August 5, 2020 9:14:48 PM GMT-03:00, Changbin Du  
> wrote:
> >On Tue, Aug 04, 2020 at 09:51:15AM -0300, Arnaldo Carvalho de Melo
> >wrote:
> >> Em Sat, Jul 18, 2020 at 02:48:09PM +0800, Changbin Du escreveu:
> >> > The '-g/-G' options have already implied function_graph tracer
> >should be
> >> > used instead of function tracer. So the extra option '--tracer' can
> >be
> >> > killed.
> >> > 
> >> > This patch changes the behavior as below:
> >> >   - By default, function tracer is used.
> >> >   - If '-g' or '-G' option is on, then function_graph tracer is
> >used.
> >> >   - The perf configuration item 'ftrace.tracer' is marked as
> >deprecated.
> >> >   - The option '--tracer' is marked as deprecated.
> >> 
> >> You should try to be more granular, for instance, I think the
> >decision
> >> to change the default is questionable, but could be acceptable.
> >> 
> >> But why deprecate the perf configuration for the default tracer?
> >> 
> >> Say people who already use 'perf ftrace ls' go and use with this
> >patch
> >> and see that it changed the default from the function_graph tracer to
> >> the function tracer and disagree with you, they want the default to
> >be
> >> the function graph tracer, know that there is (or there was) a
> >> ftrace.tracer in ~/.prefconfig, and then try that, only to find out
> >that
> >> it is not possible, frustrating :-\
> >> 
> >> So can we please remove this deprecation of ftrace.tracer so that
> >people
> >> used to how it was can get that behaviour back?
> >> 
> >Agreed. If no -F or -G is given, we can use the ftrace.tracer as
> >default tracer.
> >Let me update it. Thanks.
> 
> Thanks, I'm general try to be as granular as possible, doing one thing per 
> patch, this way the reviewer can do some preliminary cherry picking and we 
> also improve git bisectability.
>
Arnaldo, I changed the policy as below:
  - Preserve the default tracerr which is function_graph.
  - If '-g' or '-G' option is on, then function_graph tracer is used.
  - If '-T' or '-N' option is on, then function tracer is used.
  - The option '--tracer' or configuration ftrace.tracer only takes
effect if neither -g/-G nor -T/-N is specified.
  - The function_graph has priority over function tracer if both -G/-g
and -T/-N are given.

Please check updatae in v8. Thanks.
> - Arnaldo
> 
> -- 
> Sent from my Android device with K-9 Mail. Please excuse my brevity.

-- 
Cheers,
Changbin Du


Re: [PATCH v7 01/18] perf ftrace: select function/function_graph tracer automatically

2020-08-05 Thread Changbin Du
On Tue, Aug 04, 2020 at 09:51:15AM -0300, Arnaldo Carvalho de Melo wrote:
> Em Sat, Jul 18, 2020 at 02:48:09PM +0800, Changbin Du escreveu:
> > The '-g/-G' options have already implied function_graph tracer should be
> > used instead of function tracer. So the extra option '--tracer' can be
> > killed.
> > 
> > This patch changes the behavior as below:
> >   - By default, function tracer is used.
> >   - If '-g' or '-G' option is on, then function_graph tracer is used.
> >   - The perf configuration item 'ftrace.tracer' is marked as deprecated.
> >   - The option '--tracer' is marked as deprecated.
> 
> You should try to be more granular, for instance, I think the decision
> to change the default is questionable, but could be acceptable.
> 
> But why deprecate the perf configuration for the default tracer?
> 
> Say people who already use 'perf ftrace ls' go and use with this patch
> and see that it changed the default from the function_graph tracer to
> the function tracer and disagree with you, they want the default to be
> the function graph tracer, know that there is (or there was) a
> ftrace.tracer in ~/.prefconfig, and then try that, only to find out that
> it is not possible, frustrating :-\
> 
> So can we please remove this deprecation of ftrace.tracer so that people
> used to how it was can get that behaviour back?
> 
Agreed. If no -F or -G is given, we can use the ftrace.tracer as default tracer.
Let me update it. Thanks.

> I'll look at the other patches so as to provide comments on all of
> them and to speed things up I may end up removing this deprecation of
> ftrace.tracer and apply the rest, we can always revisit parts that I
> remove.
> 
> - Arnaldo
> 
> > Here are some examples.
> > 
> > This will start tracing all functions using function tracer:
> >   $ sudo perf ftrace
> > 
> > This will trace all functions using function graph tracer:
> >   $ sudo perf ftrace -G '*'
> > 
> > This will trace function vfs_read using function graph tracer:
> >   $ sudo perf ftrace -G vfs_read
> > 
> > Signed-off-by: Changbin Du 
> > 
> > ---
> > v3: remove default '*' for -G/-T.
> > ---
> >  tools/perf/Documentation/perf-config.txt |  5 -
> >  tools/perf/Documentation/perf-ftrace.txt |  2 +-
> >  tools/perf/builtin-ftrace.c  | 15 ++-
> >  3 files changed, 11 insertions(+), 11 deletions(-)
> > 
> > diff --git a/tools/perf/Documentation/perf-config.txt 
> > b/tools/perf/Documentation/perf-config.txt
> > index c7d3df5798e2..a25fee7de3b2 100644
> > --- a/tools/perf/Documentation/perf-config.txt
> > +++ b/tools/perf/Documentation/perf-config.txt
> > @@ -612,11 +612,6 @@ trace.*::
> > "libbeauty", the default, to use the same argument beautifiers 
> > used in the
> > strace-like sys_enter+sys_exit lines.
> >  
> > -ftrace.*::
> > -   ftrace.tracer::
> > -   Can be used to select the default tracer. Possible values are
> > -   'function' and 'function_graph'.
> > -
> >  llvm.*::
> > llvm.clang-path::
> > Path to clang. If omit, search it from $PATH.
> > diff --git a/tools/perf/Documentation/perf-ftrace.txt 
> > b/tools/perf/Documentation/perf-ftrace.txt
> > index b80c84307dc9..952e46669168 100644
> > --- a/tools/perf/Documentation/perf-ftrace.txt
> > +++ b/tools/perf/Documentation/perf-ftrace.txt
> > @@ -24,7 +24,7 @@ OPTIONS
> >  
> >  -t::
> >  --tracer=::
> > -   Tracer to use: function_graph or function.
> > +   Tracer to use: function_graph or function. This option is deprecated.
> >  
> >  -v::
> >  --verbose=::
> > diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
> > index 2bfc1b0db536..5f53da87040d 100644
> > --- a/tools/perf/builtin-ftrace.c
> > +++ b/tools/perf/builtin-ftrace.c
> > @@ -27,7 +27,6 @@
> >  #include "util/cap.h"
> >  #include "util/config.h"
> >  
> > -#define DEFAULT_TRACER  "function_graph"
> >  
> >  struct perf_ftrace {
> > struct evlist   *evlist;
> > @@ -419,6 +418,7 @@ static int perf_ftrace_config(const char *var, const 
> > char *value, void *cb)
> > if (strcmp(var, "ftrace.tracer"))
> > return -1;
> >  
> > +   pr_warning("Configuration ftrace.tracer is deprecated\n");
> > if (!strcmp(value, "function_graph&quo

Re: [PATCH v7 00/18] perf: ftrace enhancement

2020-07-31 Thread Changbin Du
Hi Arnaldo,
Are we ready to merge this serias now? Thanks. :)

On Sat, Jul 18, 2020 at 02:48:08PM +0800, Changbin Du wrote:
> The perf has basic kernel ftrace support but lack support of most tracing
> options. This serias is target to enhance the perf ftrace functionality so
> that we can make full use of kernel ftrace with perf.
> 
> In general, this serias be cataloged into two main changes:
>   1) Improve usability of existing functions. For example, we don't need to 
> type
>  extra option to select the tracer.
>   2) Add new options to support all other ftrace functions.
> 
> Here is a glance of all ftrace functions with this serias:
> 
> $ sudo perf ftrace -h
> 
>  Usage: perf ftrace [] []
> or: perf ftrace [] --  []
> 
> -a, --all-cpussystem-wide collection from all CPUs
> -C, --cpulist of cpus to monitor
> -D, --delayms to wait before starting tracing after program 
> start
> -F, --funcs   Show available functions to filter
> -G, --graph-funcs 
>   trace given functions using function_graph tracer
> -g, --nograph-funcs 
>   Set nograph filter on given functions
> -m, --buffer-size 
>   size of per cpu buffer
> -N, --notrace-funcs 
>   do not trace given functions
> -p, --pidtrace on existing process id
> -T, --trace-funcs 
>   trace given functions using function tracer
> -t, --tracer 
>   tracer to use: function or function_graph (This 
> option is deprecated)
> -v, --verbose be more verbose
> --func-opts 
>   function tracer options, available options: 
> call-graph,irq-info
> --graph-opts 
>   graph tracer options, available options: 
> nosleep-time,noirqs,verbose,thresh=,depth=
> --inherit trace children processes
> --tidtrace on existing thread id (exclusive to --pid)
> 
> v7:
>   o add back '--tid '.
> v6:
>   o fix return value of read_tracing_file_to_stdout().
>   o make __cmd_ftrace() shorter.
>   o remove option '-t, --tid '.
> v5:
>   o trivial fixes.
> v4:
>   o add util/parse-sublevel-options.c
>   O remove -D/--graph-depth
> v3:
>   o add --func-opts and --graph-opts to set tracer specific options.
>   o support units as a suffix for option '-m/--buffer-size'.
> v2:
>   o patches for option '-u/--userstacktrace' and '--no-pager' are dropped.
>   o update all related perf documentation.
>   o rename some options. Now all funcgraph tracer options are prefixed with
> '--graph-', while all function tracer options are prefixed with '--func-'.
>   o mark old options deprecated instead of removing them.
> 
> 
> Changbin Du (18):
>   perf ftrace: select function/function_graph tracer automatically
>   perf ftrace: add option '-F/--funcs' to list available functions
>   perf ftrace: factor out function write_tracing_file_int()
>   perf ftrace: add option '-m/--buffer-size' to set per-cpu buffer size
>   perf ftrace: show trace column header
>   perf ftrace: add option '--inherit' to trace children processes
>   perf: util: add general function to parse sublevel options
>   perf ftrace: add support for tracing option 'func_stack_trace'
>   perf ftrace: add support for trace option sleep-time
>   perf ftrace: add support for trace option funcgraph-irqs
>   perf ftrace: add support for tracing option 'irq-info'
>   perf ftrace: add option 'verbose' to show more info for graph tracer
>   perf ftrace: add support for trace option tracing_thresh
>   perf: ftrace: allow set graph depth by '--graph-opts'
>   perf ftrace: add option -D/--delay to delay tracing
>   perf ftrace: add option --tid to filter by thread id
>   perf: ftrace: Add set_tracing_options() to set all trace options
>   perf ftrace: add change log
> 
>  tools/perf/Documentation/perf-config.txt |   5 -
>  tools/perf/Documentation/perf-ftrace.txt |  36 +-
>  tools/perf/builtin-ftrace.c  | 415 +--
>  tools/perf/util/Build|   1 +
>  tools/perf/util/debug.c  |  61 +---
>  tools/perf/util/parse-sublevel-options.c |  70 
>  tools/perf/util/parse-sublevel-options.h |  11 +
>  7 files changed, 513 insertions(+), 86 deletions(-)
>  create mode 100644 tools/perf/util/parse-sublevel-options.c
>  create mode 100644 tools/perf/util/parse-sublevel-options.h
> 
> -- 
> 2.25.1
> 

-- 
Cheers,
Changbin Du


Re: [PATCH v5 02/17] perf ftrace: add option '-F/--funcs' to list available functions

2020-07-18 Thread Changbin Du
On Fri, Jul 17, 2020 at 11:05:04AM -0400, Steven Rostedt wrote:
> On Sat, 11 Jul 2020 20:40:20 +0800
> Changbin Du  wrote:
> 
> > This adds an option '-F/--funcs' to list all available functions to trace,
> > which is read from tracing file 'available_filter_functions'.
> > 
> > $ sudo ./perf ftrace -F | head
> > trace_initcall_finish_cb
> > initcall_blacklisted
> > do_one_initcall
> > do_one_initcall
> > trace_initcall_start_cb
> > run_init_process
> > try_to_run_init_process
> > match_dev_by_label
> > match_dev_by_uuid
> > rootfs_init_fs_context
> > 
> > Signed-off-by: Changbin Du 
> > 
> > ---
> > v2: option name '-l/--list-functions' -> '-F/--funcs'
> > ---
> >  tools/perf/Documentation/perf-ftrace.txt |  4 +++
> >  tools/perf/builtin-ftrace.c  | 43 
> >  2 files changed, 47 insertions(+)
> > 
> > diff --git a/tools/perf/Documentation/perf-ftrace.txt 
> > b/tools/perf/Documentation/perf-ftrace.txt
> > index 952e46669168..d79560dea19f 100644
> > --- a/tools/perf/Documentation/perf-ftrace.txt
> > +++ b/tools/perf/Documentation/perf-ftrace.txt
> > @@ -30,6 +30,10 @@ OPTIONS
> >  --verbose=::
> >  Verbosity level.
> >  
> > +-F::
> > +--funcs::
> > +List all available functions to trace.
> > +
> >  -p::
> >  --pid=::
> > Trace on existing process id (comma separated list).
> > diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
> > index 5f53da87040d..244cc8e6bd60 100644
> > --- a/tools/perf/builtin-ftrace.c
> > +++ b/tools/perf/builtin-ftrace.c
> > @@ -32,6 +32,7 @@ struct perf_ftrace {
> > struct evlist   *evlist;
> > struct target   target;
> > const char  *tracer;
> > +   boollist_avail_functions;
> > struct list_headfilters;
> > struct list_headnotrace;
> > struct list_headgraph_funcs;
> > @@ -127,6 +128,43 @@ static int append_tracing_file(const char *name, const 
> > char *val)
> > return __write_tracing_file(name, val, true);
> >  }
> >  
> > +static int read_tracing_file_to_stdout(const char *name)
> > +{
> 
> All this is looking like its duplicating code that we are working on
> for libtracefs. 
> 
> Would you like to start contributing to that, and when we get the
> libtracefs.so packed in distributions, we can easily create the
> perf ftrace without having to rewrite the wheel 10 times?
> 
> -- Steve
Yes, I'd like to join the development of libtracefs. But honestly speaking,
I am not sure whether I can get enough time on it since I have to take care
of my little baby :).

I have the same opinion with Arnaldo that we can merge what we'v already
done here. Then consider to migrate to libtracefs instead before adding
more new features.

-- 
Cheers,
Changbin Du


[PATCH v7 18/18] perf ftrace: add change log

2020-07-17 Thread Changbin Du
Add a change log after previous enhancements.

Signed-off-by: Changbin Du 
---
 tools/perf/builtin-ftrace.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 4551d4d4bcc5..9213fb9777c4 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -3,6 +3,7 @@
  * builtin-ftrace.c
  *
  * Copyright (c) 2013  LG Electronics,  Namhyung Kim 
+ * Copyright (c) 2020  Changbin Du , significant 
enhancement.
  */
 
 #include "builtin.h"
-- 
2.25.1



[PATCH v7 17/18] perf: ftrace: Add set_tracing_options() to set all trace options

2020-07-17 Thread Changbin Du
Now the __cmd_ftrace() becomes a bit long. This moves the trace
option setting code to a separate function set_tracing_options().

Suggested-by: Namhyung Kim 
Signed-off-by: Changbin Du 
---
 tools/perf/builtin-ftrace.c | 118 +++-
 1 file changed, 63 insertions(+), 55 deletions(-)

diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index b07f71722b97..4551d4d4bcc5 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -463,110 +463,118 @@ static int set_tracing_thresh(struct perf_ftrace 
*ftrace)
return 0;
 }
 
-static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
**argv)
+static int set_tracing_options(struct perf_ftrace *ftrace)
 {
-   char *trace_file;
-   int trace_fd;
-   char buf[4096];
-   struct pollfd pollfd = {
-   .events = POLLIN,
-   };
-
-   if (!(perf_cap__capable(CAP_PERFMON) ||
- perf_cap__capable(CAP_SYS_ADMIN))) {
-   pr_err("ftrace only works for %s!\n",
-#ifdef HAVE_LIBCAP_SUPPORT
-   "users with the CAP_PERFMON or CAP_SYS_ADMIN capability"
-#else
-   "root"
-#endif
-   );
-   return -1;
-   }
-
-   signal(SIGINT, sig_handler);
-   signal(SIGUSR1, sig_handler);
-   signal(SIGCHLD, sig_handler);
-   signal(SIGPIPE, sig_handler);
-
-   if (ftrace->list_avail_functions)
-   return 
read_tracing_file_to_stdout("available_filter_functions");
-
-   if (reset_tracing_files(ftrace) < 0) {
-   pr_err("failed to reset ftrace\n");
-   goto out;
-   }
-
-   /* reset ftrace buffer */
-   if (write_tracing_file("trace", "0") < 0)
-   goto out;
-
-   if (argc && perf_evlist__prepare_workload(ftrace->evlist,
-   &ftrace->target, argv, false,
-   ftrace__workload_exec_failed_signal) < 0) {
-   goto out;
-   }
-
if (set_tracing_pid(ftrace) < 0) {
pr_err("failed to set ftrace pid\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_cpu(ftrace) < 0) {
pr_err("failed to set tracing cpumask\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_func_stack_trace(ftrace) < 0) {
pr_err("failed to set tracing option func_stack_trace\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_func_irqinfo(ftrace) < 0) {
pr_err("failed to set tracing option irq-info\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_filters(ftrace) < 0) {
pr_err("failed to set tracing filters\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_depth(ftrace) < 0) {
pr_err("failed to set graph depth\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_percpu_buffer_size(ftrace) < 0) {
pr_err("failed to set tracing per-cpu buffer size\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_trace_inherit(ftrace) < 0) {
pr_err("failed to set tracing option function-fork\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_sleep_time(ftrace) < 0) {
pr_err("failed to set tracing option sleep-time\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_funcgraph_irqs(ftrace) < 0) {
pr_err("failed to set tracing option funcgraph-irqs\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_funcgraph_verbose(ftrace) < 0) {
pr_err("failed to set tracing option 
funcgraph-proc/funcgraph-abstime\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_thresh(ftrace) < 0) {
pr_err("failed to set tracing thresh\n");
-   goto out_reset;
+   return -1;
+   }
+
+   return 0;
+}
+
+static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
**argv)
+{
+   char *trace_file;
+   int trace_fd;
+   char buf[4096];
+   struct pollfd pollfd = {
+   .events = POLLIN,
+   };
+
+   if (!(perf_cap__capable(CAP_PERFMON) ||
+ perf_cap__capable(CAP_SYS_ADMIN))) {
+   pr_err("ftrace only works for %s!\n",
+#ifdef HAVE_LIBCAP_SUPPORT

[PATCH v7 13/18] perf ftrace: add support for trace option tracing_thresh

2020-07-17 Thread Changbin Du
This adds an option '--graph-opts thresh' to setup trace duration
threshold for funcgraph tracer.

$ sudo ./perf ftrace -G '*' --graph-opts thresh=100
 3) ! 184.060 us  |} /* schedule */
 3) ! 185.600 us  |  } /* exit_to_usermode_loop */
 2) ! 225.989 us  |} /* schedule_idle */
 2) # 4140.051 us |  } /* do_idle */

Signed-off-by: Changbin Du 
---
 tools/perf/Documentation/perf-ftrace.txt |  1 +
 tools/perf/builtin-ftrace.c  | 26 +++-
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 319ec6375228..96e5e8d7f65c 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -104,6 +104,7 @@ OPTIONS
  nosleep-time - Measure on-CPU time only for function_graph tracer.
  noirqs   - Ignore functions that happen inside interrupt.
  verbose  - Show process names, PIDs, timestamps, etc.
+ thresh=   - Setup trace duration threshold in microseconds.
 
 SEE ALSO
 
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 0d893d97691d..5d948239bd70 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -46,6 +46,7 @@ struct perf_ftrace {
int graph_nosleep_time;
int graph_noirqs;
int graph_verbose;
+   int graph_thresh;
 };
 
 struct filter_entry {
@@ -232,6 +233,9 @@ static int reset_tracing_files(struct perf_ftrace *ftrace 
__maybe_unused)
if (write_tracing_file("max_graph_depth", "0") < 0)
return -1;
 
+   if (write_tracing_file("tracing_thresh", "0") < 0)
+   return -1;
+
reset_tracing_filters();
reset_tracing_options(ftrace);
return 0;
@@ -444,6 +448,20 @@ static int set_tracing_funcgraph_verbose(struct 
perf_ftrace *ftrace)
return 0;
 }
 
+static int set_tracing_thresh(struct perf_ftrace *ftrace)
+{
+   int ret;
+
+   if (ftrace->graph_thresh == 0)
+   return 0;
+
+   ret = write_tracing_file_int("tracing_thresh", ftrace->graph_thresh);
+   if (ret < 0)
+   return ret;
+
+   return 0;
+}
+
 static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
**argv)
 {
char *trace_file;
@@ -543,6 +561,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
goto out_reset;
}
 
+   if (set_tracing_thresh(ftrace) < 0) {
+   pr_err("failed to set tracing thresh\n");
+   goto out_reset;
+   }
+
if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
goto out_reset;
@@ -726,6 +749,7 @@ static int parse_graph_tracer_opts(const struct option *opt,
{ .name = "nosleep-time",   .value_ptr = 
&ftrace->graph_nosleep_time },
{ .name = "noirqs", .value_ptr = 
&ftrace->graph_noirqs },
{ .name = "verbose",.value_ptr = 
&ftrace->graph_verbose },
+   { .name = "thresh", .value_ptr = 
&ftrace->graph_thresh },
{ .name = NULL, }
};
 
@@ -780,7 +804,7 @@ int cmd_ftrace(int argc, const char **argv)
OPT_INTEGER('D', "graph-depth", &ftrace.graph_depth,
"Max depth for function graph tracer"),
OPT_CALLBACK(0, "graph-opts", &ftrace, "options",
-"graph tracer options, available options: 
nosleep-time,noirqs,verbose",
+"graph tracer options, available options: 
nosleep-time,noirqs,verbose,thresh=",
 parse_graph_tracer_opts),
OPT_CALLBACK('m', "buffer-size", &ftrace.percpu_buffer_size, "size",
 "size of per cpu buffer", parse_buffer_size),
-- 
2.25.1



[PATCH v7 16/18] perf ftrace: add option --tid to filter by thread id

2020-07-17 Thread Changbin Du
This allows us to trace single thread instead of the whole process.

Signed-off-by: Changbin Du 
---
 tools/perf/Documentation/perf-ftrace.txt | 3 +++
 tools/perf/builtin-ftrace.c  | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 077249c979f2..546a8cd01b7e 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -38,6 +38,9 @@ OPTIONS
 --pid=::
Trace on existing process id (comma separated list).
 
+--tid=::
+   Trace on existing thread id (comma separated list).
+
 -D::
 --delay::
Time (ms) to wait before starting tracing after program start.
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 64b68331048a..b07f71722b97 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -794,6 +794,9 @@ int cmd_ftrace(int argc, const char **argv)
"Show available functions to filter"),
OPT_STRING('p', "pid", &ftrace.target.pid, "pid",
   "trace on existing process id"),
+   /* TODO: Add short option -t after -t/--tracer can be removed. */
+   OPT_STRING(0, "tid", &ftrace.target.tid, "tid",
+  "trace on existing thread id (exclusive to --pid)"),
OPT_INCR('v', "verbose", &verbose,
 "be more verbose"),
OPT_BOOLEAN('a', "all-cpus", &ftrace.target.system_wide,
-- 
2.25.1



[PATCH v7 12/18] perf ftrace: add option 'verbose' to show more info for graph tracer

2020-07-17 Thread Changbin Du
Sometimes we want ftrace display more and longer information about
the trace.

$ sudo perf ftrace -G '*'
 2)   0.979 us|  mutex_unlock();
 2)   1.540 us|  __fsnotify_parent();
 2)   0.433 us|  fsnotify();

$ sudo perf ftrace -G '*' --graph-opts verbose
14160.770883 |   0)  <...>-47814   |   |   1.289 us|  mutex_unlock();
14160.770886 |   0)  <...>-47814   |   |   1.624 us|  
__fsnotify_parent();
14160.770887 |   0)  <...>-47814   |   |   0.636 us|  fsnotify();
14160.770888 |   0)  <...>-47814   |   |   0.328 us|  __sb_end_write();
14160.770888 |   0)  <...>-47814   |  d... |   0.430 us|  
fpregs_assert_state_consistent();
14160.770889 |   0)  <...>-47814   |  d... |   |  do_syscall_64() {
14160.770889 |   0)  <...>-47814   |  .... |       |
__x64_sys_close() {

Signed-off-by: Changbin Du 
---
 tools/perf/Documentation/perf-ftrace.txt |  1 +
 tools/perf/builtin-ftrace.c  | 29 +++-
 2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 3ab1fe040994..319ec6375228 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -103,6 +103,7 @@ OPTIONS
List of options allowed to set:
  nosleep-time - Measure on-CPU time only for function_graph tracer.
  noirqs   - Ignore functions that happen inside interrupt.
+ verbose  - Show process names, PIDs, timestamps, etc.
 
 SEE ALSO
 
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 95d87c5966ad..0d893d97691d 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -45,6 +45,7 @@ struct perf_ftrace {
int func_irq_info;
int graph_nosleep_time;
int graph_noirqs;
+   int graph_verbose;
 };
 
 struct filter_entry {
@@ -208,6 +209,9 @@ static void reset_tracing_options(struct perf_ftrace 
*ftrace __maybe_unused)
write_tracing_option_file("func_stack_trace", "0");
write_tracing_option_file("sleep-time", "1");
write_tracing_option_file("funcgraph-irqs", "1");
+   write_tracing_option_file("funcgraph-proc", "0");
+   write_tracing_option_file("funcgraph-abstime", "0");
+   write_tracing_option_file("latency-format", "0");
write_tracing_option_file("irq-info", "0");
 }
 
@@ -423,6 +427,23 @@ static int set_tracing_funcgraph_irqs(struct perf_ftrace 
*ftrace)
return 0;
 }
 
+static int set_tracing_funcgraph_verbose(struct perf_ftrace *ftrace)
+{
+   if (!ftrace->graph_verbose)
+   return 0;
+
+   if (write_tracing_option_file("funcgraph-proc", "1") < 0)
+   return -1;
+
+   if (write_tracing_option_file("funcgraph-abstime", "1") < 0)
+   return -1;
+
+   if (write_tracing_option_file("latency-format", "1") < 0)
+   return -1;
+
+   return 0;
+}
+
 static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
**argv)
 {
char *trace_file;
@@ -517,6 +538,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
goto out_reset;
}
 
+   if (set_tracing_funcgraph_verbose(ftrace) < 0) {
+   pr_err("failed to set tracing option 
funcgraph-proc/funcgraph-abstime\n");
+   goto out_reset;
+   }
+
if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
goto out_reset;
@@ -699,6 +725,7 @@ static int parse_graph_tracer_opts(const struct option *opt,
struct sublevel_option graph_tracer_opts[] = {
{ .name = "nosleep-time",   .value_ptr = 
&ftrace->graph_nosleep_time },
{ .name = "noirqs", .value_ptr = 
&ftrace->graph_noirqs },
+   { .name = "verbose",.value_ptr = 
&ftrace->graph_verbose },
{ .name = NULL, }
};
 
@@ -753,7 +780,7 @@ int cmd_ftrace(int argc, const char **argv)
OPT_INTEGER('D', "graph-depth", &ftrace.graph_depth,
"Max depth for function graph tracer"),
OPT_CALLBACK(0, "graph-opts", &ftrace, "options",
-"graph tracer options, available options: 
nosleep-time,noirqs",
+"graph tracer options, available options: 
nosleep-time,noirqs,verbose",
 parse_graph_tracer_opts),
OPT_CALLBACK('m', "buffer-size", &ftrace.percpu_buffer_size, "size",
 "size of per cpu buffer", parse_buffer_size),
-- 
2.25.1



[PATCH v7 15/18] perf ftrace: add option -D/--delay to delay tracing

2020-07-17 Thread Changbin Du
This adds an option '-D/--delay' to allow us to start tracing some
times later after workload is launched.

Signed-off-by: Changbin Du 
---
 tools/perf/Documentation/perf-ftrace.txt |  4 
 tools/perf/builtin-ftrace.c  | 19 ---
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 6f17939b8789..077249c979f2 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -38,6 +38,10 @@ OPTIONS
 --pid=::
Trace on existing process id (comma separated list).
 
+-D::
+--delay::
+   Time (ms) to wait before starting tracing after program start.
+
 -a::
 --all-cpus::
Force system-wide collection.  Scripts run without a 
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 3ddd7568b456..64b68331048a 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -47,6 +47,7 @@ struct perf_ftrace {
int graph_noirqs;
int graph_verbose;
int graph_thresh;
+   unsigned intinitial_delay;
 };
 
 struct filter_entry {
@@ -594,13 +595,23 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
/* display column headers */
read_tracing_file_to_stdout("trace");
 
-   if (write_tracing_file("tracing_on", "1") < 0) {
-   pr_err("can't enable tracing\n");
-   goto out_close_fd;
+   if (!ftrace->initial_delay) {
+   if (write_tracing_file("tracing_on", "1") < 0) {
+   pr_err("can't enable tracing\n");
+   goto out_close_fd;
+   }
}
 
perf_evlist__start_workload(ftrace->evlist);
 
+   if (ftrace->initial_delay) {
+   usleep(ftrace->initial_delay * 1000);
+   if (write_tracing_file("tracing_on", "1") < 0) {
+   pr_err("can't enable tracing\n");
+   goto out_close_fd;
+   }
+   }
+
while (!done) {
if (poll(&pollfd, 1, -1) < 0)
break;
@@ -809,6 +820,8 @@ int cmd_ftrace(int argc, const char **argv)
 "size of per cpu buffer", parse_buffer_size),
OPT_BOOLEAN(0, "inherit", &ftrace.inherit,
"trace children processes"),
+   OPT_UINTEGER('D', "delay", &ftrace.initial_delay,
+"ms to wait before starting tracing after program start"),
OPT_END()
};
 
-- 
2.25.1



[PATCH v7 14/18] perf: ftrace: allow set graph depth by '--graph-opts'

2020-07-17 Thread Changbin Du
This is to have a consistent view of all graph tracer options.
The original option '--graph-depth' is marked as deprecated.

Signed-off-by: Changbin Du 
---
 tools/perf/Documentation/perf-ftrace.txt | 5 +
 tools/perf/builtin-ftrace.c  | 5 ++---
 2 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 96e5e8d7f65c..6f17939b8789 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -95,16 +95,13 @@ OPTIONS
This can be used more than once to specify multiple functions.
It will be passed to 'set_graph_notrace' in tracefs.
 
--D::
---graph-depth=::
-   Set max depth for function graph tracer to follow
-
 --graph-opts::
List of options allowed to set:
  nosleep-time - Measure on-CPU time only for function_graph tracer.
  noirqs   - Ignore functions that happen inside interrupt.
  verbose  - Show process names, PIDs, timestamps, etc.
  thresh=   - Setup trace duration threshold in microseconds.
+ depth=- Set max depth for function graph tracer to follow.
 
 SEE ALSO
 
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 5d948239bd70..3ddd7568b456 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -750,6 +750,7 @@ static int parse_graph_tracer_opts(const struct option *opt,
{ .name = "noirqs", .value_ptr = 
&ftrace->graph_noirqs },
{ .name = "verbose",.value_ptr = 
&ftrace->graph_verbose },
{ .name = "thresh", .value_ptr = 
&ftrace->graph_thresh },
+   { .name = "depth",  .value_ptr = 
&ftrace->graph_depth },
{ .name = NULL, }
};
 
@@ -801,10 +802,8 @@ int cmd_ftrace(int argc, const char **argv)
 parse_filter_func),
OPT_CALLBACK('g', "nograph-funcs", &ftrace.nograph_funcs, "func",
 "Set nograph filter on given functions", 
parse_filter_func),
-   OPT_INTEGER('D', "graph-depth", &ftrace.graph_depth,
-   "Max depth for function graph tracer"),
OPT_CALLBACK(0, "graph-opts", &ftrace, "options",
-"graph tracer options, available options: 
nosleep-time,noirqs,verbose,thresh=",
+"graph tracer options, available options: 
nosleep-time,noirqs,verbose,thresh=,depth=",
 parse_graph_tracer_opts),
OPT_CALLBACK('m', "buffer-size", &ftrace.percpu_buffer_size, "size",
 "size of per cpu buffer", parse_buffer_size),
-- 
2.25.1



[PATCH v7 06/18] perf ftrace: add option '--inherit' to trace children processes

2020-07-17 Thread Changbin Du
This adds an option '--inherit' to allow us trace children
processes spawned by our target.

Signed-off-by: Changbin Du 

---
v2: option name '--trace-children' -> '--inherit'.
---
 tools/perf/Documentation/perf-ftrace.txt |  3 ++
 tools/perf/builtin-ftrace.c  | 38 
 2 files changed, 41 insertions(+)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index dcac0d75a0e5..3eee073a7042 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -57,6 +57,9 @@ OPTIONS
Set the size of per-cpu tracing buffer,  is expected to
be a number with appended unit character - B/K/M/G.
 
+--inherit::
+   Trace children processes spawned by our target.
+
 -T::
 --trace-funcs=::
Only trace functions given by the argument.  Multiple functions
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 6ce626a2d0d1..765ebd56e05f 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -39,6 +39,7 @@ struct perf_ftrace {
struct list_headnograph_funcs;
int graph_depth;
unsigned long   percpu_buffer_size;
+   boolinherit;
 };
 
 struct filter_entry {
@@ -180,9 +181,27 @@ static int write_tracing_file_int(const char *name, int 
value)
return 0;
 }
 
+static int write_tracing_option_file(const char *name, const char *val)
+{
+   char *file;
+   int ret;
+
+   if (asprintf(&file, "options/%s", name) < 0)
+   return -1;
+
+   ret = __write_tracing_file(file, val, false);
+   free(file);
+   return ret;
+}
+
 static int reset_tracing_cpu(void);
 static void reset_tracing_filters(void);
 
+static void reset_tracing_options(struct perf_ftrace *ftrace __maybe_unused)
+{
+   write_tracing_option_file("function-fork", "0");
+}
+
 static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
 {
if (write_tracing_file("tracing_on", "0") < 0)
@@ -201,6 +220,7 @@ static int reset_tracing_files(struct perf_ftrace *ftrace 
__maybe_unused)
return -1;
 
reset_tracing_filters();
+   reset_tracing_options(ftrace);
return 0;
 }
 
@@ -339,6 +359,17 @@ static int set_tracing_percpu_buffer_size(struct 
perf_ftrace *ftrace)
return 0;
 }
 
+static int set_tracing_trace_inherit(struct perf_ftrace *ftrace)
+{
+   if (!ftrace->inherit)
+   return 0;
+
+   if (write_tracing_option_file("function-fork", "1") < 0)
+   return -1;
+
+   return 0;
+}
+
 static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
**argv)
 {
char *trace_file;
@@ -408,6 +439,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
goto out_reset;
}
 
+   if (set_tracing_trace_inherit(ftrace) < 0) {
+   pr_err("failed to set tracing option function-fork\n");
+   goto out_reset;
+   }
+
if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
goto out_reset;
@@ -600,6 +636,8 @@ int cmd_ftrace(int argc, const char **argv)
"Max depth for function graph tracer"),
OPT_CALLBACK('m', "buffer-size", &ftrace.percpu_buffer_size, "size",
 "size of per cpu buffer", parse_buffer_size),
+   OPT_BOOLEAN(0, "inherit", &ftrace.inherit,
+   "trace children processes"),
OPT_END()
};
 
-- 
2.25.1



[PATCH v7 07/18] perf: util: add general function to parse sublevel options

2020-07-17 Thread Changbin Du
This factors out a general function perf_parse_sublevel_options() to parse
sublevel options. The 'sublevel' options is something like the '--debug'
options which allow more sublevel options.

Signed-off-by: Changbin Du 

---
v2: add util/parse-sublevel-options.c
---
 tools/perf/util/Build|  1 +
 tools/perf/util/debug.c  | 61 ++---
 tools/perf/util/parse-sublevel-options.c | 70 
 tools/perf/util/parse-sublevel-options.h | 11 
 4 files changed, 99 insertions(+), 44 deletions(-)
 create mode 100644 tools/perf/util/parse-sublevel-options.c
 create mode 100644 tools/perf/util/parse-sublevel-options.h

diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 8d18380ecd10..e86607ada0b5 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -117,6 +117,7 @@ endif
 perf-y += parse-branch-options.o
 perf-y += dump-insn.o
 perf-y += parse-regs-options.o
+perf-y += parse-sublevel-options.o
 perf-y += term.o
 perf-y += help-unknown-cmd.o
 perf-y += mem-events.o
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index adb656745ecc..5cda5565777a 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -20,6 +20,7 @@
 #include "target.h"
 #include "ui/helpline.h"
 #include "ui/ui.h"
+#include "util/parse-sublevel-options.h"
 
 #include 
 
@@ -173,65 +174,37 @@ void trace_event(union perf_event *event)
 trace_event_printer, event);
 }
 
-static struct debug_variable {
-   const char *name;
-   int *ptr;
-} debug_variables[] = {
-   { .name = "verbose",.ptr = &verbose },
-   { .name = "ordered-events", .ptr = &debug_ordered_events},
-   { .name = "stderr", .ptr = &redirect_to_stderr},
-   { .name = "data-convert",   .ptr = &debug_data_convert },
-   { .name = "perf-event-open",.ptr = &debug_peo_args },
+static struct sublevel_option debug_opts[] = {
+   { .name = "verbose",.value_ptr = &verbose },
+   { .name = "ordered-events", .value_ptr = &debug_ordered_events},
+   { .name = "stderr", .value_ptr = &redirect_to_stderr},
+   { .name = "data-convert",   .value_ptr = &debug_data_convert },
+   { .name = "perf-event-open",.value_ptr = &debug_peo_args },
{ .name = NULL, }
 };
 
 int perf_debug_option(const char *str)
 {
-   struct debug_variable *var = &debug_variables[0];
-   char *vstr, *s = strdup(str);
-   int v = 1;
-
-   vstr = strchr(s, '=');
-   if (vstr)
-   *vstr++ = 0;
-
-   while (var->name) {
-   if (!strcmp(s, var->name))
-   break;
-   var++;
-   }
-
-   if (!var->name) {
-   pr_err("Unknown debug variable name '%s'\n", s);
-   free(s);
-   return -1;
-   }
+   int ret;
 
-   if (vstr) {
-   v = atoi(vstr);
-   /*
-* Allow only values in range (0, 10),
-* otherwise set 0.
-*/
-   v = (v < 0) || (v > 10) ? 0 : v;
-   }
+   ret = perf_parse_sublevel_options(str, debug_opts);
+   if (ret)
+   return ret;
 
-   if (quiet)
-   v = -1;
+   /* Allow only verbose value in range (0, 10), otherwise set 0. */
+   verbose = (verbose < 0) || (verbose > 10) ? 0 : verbose;
 
-   *var->ptr = v;
-   free(s);
return 0;
 }
 
 int perf_quiet_option(void)
 {
-   struct debug_variable *var = &debug_variables[0];
+   struct sublevel_option *opt = &debug_opts[0];
 
/* disable all debug messages */
-   while (var->name) {
-   *var->ptr = -1;
-   var++;
+   while (opt->name) {
+   *opt->value_ptr = -1;
+   opt++;
}
 
return 0;
diff --git a/tools/perf/util/parse-sublevel-options.c 
b/tools/perf/util/parse-sublevel-options.c
new file mode 100644
index ..a841d17ffd57
--- /dev/null
+++ b/tools/perf/util/parse-sublevel-options.c
@@ -0,0 +1,70 @@
+#include 
+#include 
+#include 
+#include 
+
+#include "util/debug.h"
+#include "util/parse-sublevel-options.h"
+
+static int parse_one_sublevel_option(const char *str,
+struct sublevel_option *opts)
+{
+   struct sublevel_option *opt = opts;
+   char *vstr, *s = strdup(str);
+   int v = 1;
+
+   if (!s) {
+   pr_err("no memory\n");
+   return -1;
+   }
+
+   vstr = strchr(s, '=');
+   if (vstr)
+   *vstr++ = 0;
+
+   while (opt->name) {

[PATCH v7 08/18] perf ftrace: add support for tracing option 'func_stack_trace'

2020-07-17 Thread Changbin Du
This adds support to display call trace for function tracer. To do this,
just specify a '--func-opts call-graph' option.

$ sudo perf ftrace -T vfs_read --func-opts call-graph
 iio-sensor-prox-855   [003]   6168.369657: vfs_read <-ksys_read
 iio-sensor-prox-855   [003]   6168.369677: 
 => vfs_read
 => ksys_read
 => __x64_sys_read
 => do_syscall_64
 => entry_SYSCALL_64_after_hwframe
 ...

Signed-off-by: Changbin Du 

---
v3: switch to uniform option --func-opts.
v2: option name '-s' -> '--func-call-graph'
---
 tools/perf/Documentation/perf-ftrace.txt |  4 +++
 tools/perf/builtin-ftrace.c  | 42 
 2 files changed, 46 insertions(+)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 3eee073a7042..5a5069306141 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -74,6 +74,10 @@ OPTIONS
(or glob patterns).  It will be passed to 'set_ftrace_notrace'
in tracefs.
 
+--func-opts::
+   List of options allowed to set:
+ call-graph - Display kernel stack trace for function tracer.
+
 -G::
 --graph-funcs=::
Set graph filter on the given function (or a glob pattern).
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 765ebd56e05f..e7c8697294f0 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -27,6 +27,7 @@
 #include "util/cap.h"
 #include "util/config.h"
 #include "util/units.h"
+#include "util/parse-sublevel-options.h"
 
 struct perf_ftrace {
struct evlist   *evlist;
@@ -40,6 +41,7 @@ struct perf_ftrace {
int graph_depth;
unsigned long   percpu_buffer_size;
boolinherit;
+   int func_stack_trace;
 };
 
 struct filter_entry {
@@ -200,6 +202,7 @@ static void reset_tracing_filters(void);
 static void reset_tracing_options(struct perf_ftrace *ftrace __maybe_unused)
 {
write_tracing_option_file("function-fork", "0");
+   write_tracing_option_file("func_stack_trace", "0");
 }
 
 static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
@@ -276,6 +279,17 @@ static int set_tracing_cpu(struct perf_ftrace *ftrace)
return set_tracing_cpumask(cpumap);
 }
 
+static int set_tracing_func_stack_trace(struct perf_ftrace *ftrace)
+{
+   if (!ftrace->func_stack_trace)
+   return 0;
+
+   if (write_tracing_option_file("func_stack_trace", "1") < 0)
+   return -1;
+
+   return 0;
+}
+
 static int reset_tracing_cpu(void)
 {
struct perf_cpu_map *cpumap = perf_cpu_map__new(NULL);
@@ -424,6 +438,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
goto out_reset;
}
 
+   if (set_tracing_func_stack_trace(ftrace) < 0) {
+   pr_err("failed to set tracing option func_stack_trace\n");
+   goto out_reset;
+   }
+
if (set_tracing_filters(ftrace) < 0) {
pr_err("failed to set tracing filters\n");
goto out_reset;
@@ -597,6 +616,26 @@ static int parse_buffer_size(const struct option *opt,
return -1;
 }
 
+static int parse_func_tracer_opts(const struct option *opt,
+ const char *str, int unset)
+{
+   int ret;
+   struct perf_ftrace *ftrace = (struct perf_ftrace *) opt->value;
+   struct sublevel_option func_tracer_opts[] = {
+   { .name = "call-graph", .value_ptr = &ftrace->func_stack_trace 
},
+   { .name = NULL, }
+   };
+
+   if (unset)
+   return 0;
+
+   ret = perf_parse_sublevel_options(str, func_tracer_opts);
+   if (ret)
+   return ret;
+
+   return 0;
+}
+
 int cmd_ftrace(int argc, const char **argv)
 {
int ret;
@@ -627,6 +666,9 @@ int cmd_ftrace(int argc, const char **argv)
 parse_filter_func),
OPT_CALLBACK('N', "notrace-funcs", &ftrace.notrace, "func",
 "do not trace given functions", parse_filter_func),
+   OPT_CALLBACK(0, "func-opts", &ftrace, "options",
+"function tracer options, available options: call-graph",
+parse_func_tracer_opts),
OPT_CALLBACK('G', "graph-funcs", &ftrace.graph_funcs, "func",
 "trace given functions using function_graph tracer",
 parse_filter_func),
-- 
2.25.1



[PATCH v7 11/18] perf ftrace: add support for tracing option 'irq-info'

2020-07-17 Thread Changbin Du
This adds support to display irq context info for function tracer. To do
this, just specify a '--func-opts irq-info' option.

Signed-off-by: Changbin Du 
---
 tools/perf/Documentation/perf-ftrace.txt |  1 +
 tools/perf/builtin-ftrace.c  | 21 -
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 21d3b444587a..3ab1fe040994 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -77,6 +77,7 @@ OPTIONS
 --func-opts::
List of options allowed to set:
  call-graph - Display kernel stack trace for function tracer.
+ irq-info   - Display irq context info for function tracer.
 
 -G::
 --graph-funcs=::
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 6402df3984c0..95d87c5966ad 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -42,6 +42,7 @@ struct perf_ftrace {
unsigned long   percpu_buffer_size;
boolinherit;
int func_stack_trace;
+   int func_irq_info;
int graph_nosleep_time;
int graph_noirqs;
 };
@@ -207,6 +208,7 @@ static void reset_tracing_options(struct perf_ftrace 
*ftrace __maybe_unused)
write_tracing_option_file("func_stack_trace", "0");
write_tracing_option_file("sleep-time", "1");
write_tracing_option_file("funcgraph-irqs", "1");
+   write_tracing_option_file("irq-info", "0");
 }
 
 static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
@@ -294,6 +296,17 @@ static int set_tracing_func_stack_trace(struct perf_ftrace 
*ftrace)
return 0;
 }
 
+static int set_tracing_func_irqinfo(struct perf_ftrace *ftrace)
+{
+   if (!ftrace->func_irq_info)
+   return 0;
+
+   if (write_tracing_option_file("irq-info", "1") < 0)
+   return -1;
+
+   return 0;
+}
+
 static int reset_tracing_cpu(void)
 {
struct perf_cpu_map *cpumap = perf_cpu_map__new(NULL);
@@ -469,6 +482,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
goto out_reset;
}
 
+   if (set_tracing_func_irqinfo(ftrace) < 0) {
+   pr_err("failed to set tracing option irq-info\n");
+   goto out_reset;
+   }
+
if (set_tracing_filters(ftrace) < 0) {
pr_err("failed to set tracing filters\n");
goto out_reset;
@@ -659,6 +677,7 @@ static int parse_func_tracer_opts(const struct option *opt,
struct perf_ftrace *ftrace = (struct perf_ftrace *) opt->value;
struct sublevel_option func_tracer_opts[] = {
{ .name = "call-graph", .value_ptr = &ftrace->func_stack_trace 
},
+   { .name = "irq-info",   .value_ptr = &ftrace->func_irq_info },
{ .name = NULL, }
};
 
@@ -724,7 +743,7 @@ int cmd_ftrace(int argc, const char **argv)
OPT_CALLBACK('N', "notrace-funcs", &ftrace.notrace, "func",
 "do not trace given functions", parse_filter_func),
OPT_CALLBACK(0, "func-opts", &ftrace, "options",
-"function tracer options, available options: call-graph",
+"function tracer options, available options: 
call-graph,irq-info",
 parse_func_tracer_opts),
OPT_CALLBACK('G', "graph-funcs", &ftrace.graph_funcs, "func",
 "trace given functions using function_graph tracer",
-- 
2.25.1



[PATCH v7 09/18] perf ftrace: add support for trace option sleep-time

2020-07-17 Thread Changbin Du
This adds an option '--graph-opts nosleep-time' which allow us
only to measure on-CPU time. This option is function_graph tracer
only.

Signed-off-by: Changbin Du 

---
v3: switch to uniform option --graph-opts.
v2: option name '--nosleep-time' -> '--graph-nosleep-time'.
---
 tools/perf/Documentation/perf-ftrace.txt |  4 +++
 tools/perf/builtin-ftrace.c  | 41 
 2 files changed, 45 insertions(+)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 5a5069306141..2968a34239a4 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -98,6 +98,10 @@ OPTIONS
 --graph-depth=::
Set max depth for function graph tracer to follow
 
+--graph-opts::
+   List of options allowed to set:
+ nosleep-time - Measure on-CPU time only for function_graph tracer.
+
 SEE ALSO
 
 linkperf:perf-record[1], linkperf:perf-trace[1]
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index e7c8697294f0..835f810985f0 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -42,6 +42,7 @@ struct perf_ftrace {
unsigned long   percpu_buffer_size;
boolinherit;
int func_stack_trace;
+   int graph_nosleep_time;
 };
 
 struct filter_entry {
@@ -203,6 +204,7 @@ static void reset_tracing_options(struct perf_ftrace 
*ftrace __maybe_unused)
 {
write_tracing_option_file("function-fork", "0");
write_tracing_option_file("func_stack_trace", "0");
+   write_tracing_option_file("sleep-time", "1");
 }
 
 static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
@@ -384,6 +386,17 @@ static int set_tracing_trace_inherit(struct perf_ftrace 
*ftrace)
return 0;
 }
 
+static int set_tracing_sleep_time(struct perf_ftrace *ftrace)
+{
+   if (!ftrace->graph_nosleep_time)
+   return 0;
+
+   if (write_tracing_option_file("sleep-time", "0") < 0)
+   return -1;
+
+   return 0;
+}
+
 static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
**argv)
 {
char *trace_file;
@@ -463,6 +476,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
goto out_reset;
}
 
+   if (set_tracing_sleep_time(ftrace) < 0) {
+   pr_err("failed to set tracing option sleep-time\n");
+   goto out_reset;
+   }
+
if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
goto out_reset;
@@ -636,6 +654,26 @@ static int parse_func_tracer_opts(const struct option *opt,
return 0;
 }
 
+static int parse_graph_tracer_opts(const struct option *opt,
+ const char *str, int unset)
+{
+   int ret;
+   struct perf_ftrace *ftrace = (struct perf_ftrace *) opt->value;
+   struct sublevel_option graph_tracer_opts[] = {
+   { .name = "nosleep-time",   .value_ptr = 
&ftrace->graph_nosleep_time },
+   { .name = NULL, }
+   };
+
+   if (unset)
+   return 0;
+
+   ret = perf_parse_sublevel_options(str, graph_tracer_opts);
+   if (ret)
+   return ret;
+
+   return 0;
+}
+
 int cmd_ftrace(int argc, const char **argv)
 {
int ret;
@@ -676,6 +714,9 @@ int cmd_ftrace(int argc, const char **argv)
 "Set nograph filter on given functions", 
parse_filter_func),
OPT_INTEGER('D', "graph-depth", &ftrace.graph_depth,
"Max depth for function graph tracer"),
+   OPT_CALLBACK(0, "graph-opts", &ftrace, "options",
+"graph tracer options, available options: nosleep-time",
+parse_graph_tracer_opts),
OPT_CALLBACK('m', "buffer-size", &ftrace.percpu_buffer_size, "size",
 "size of per cpu buffer", parse_buffer_size),
OPT_BOOLEAN(0, "inherit", &ftrace.inherit,
-- 
2.25.1



[PATCH v7 10/18] perf ftrace: add support for trace option funcgraph-irqs

2020-07-17 Thread Changbin Du
This adds an option '--graph-opts noirqs' to filter out functions executed
in irq context.

Signed-off-by: Changbin Du 

---
v2: option name '--nofuncgraph-irqs' -> '--graph-noirqs'.
---
 tools/perf/Documentation/perf-ftrace.txt |  1 +
 tools/perf/builtin-ftrace.c  | 21 -
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 2968a34239a4..21d3b444587a 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -101,6 +101,7 @@ OPTIONS
 --graph-opts::
List of options allowed to set:
  nosleep-time - Measure on-CPU time only for function_graph tracer.
+ noirqs   - Ignore functions that happen inside interrupt.
 
 SEE ALSO
 
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 835f810985f0..6402df3984c0 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -43,6 +43,7 @@ struct perf_ftrace {
boolinherit;
int func_stack_trace;
int graph_nosleep_time;
+   int graph_noirqs;
 };
 
 struct filter_entry {
@@ -205,6 +206,7 @@ static void reset_tracing_options(struct perf_ftrace 
*ftrace __maybe_unused)
write_tracing_option_file("function-fork", "0");
write_tracing_option_file("func_stack_trace", "0");
write_tracing_option_file("sleep-time", "1");
+   write_tracing_option_file("funcgraph-irqs", "1");
 }
 
 static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
@@ -397,6 +399,17 @@ static int set_tracing_sleep_time(struct perf_ftrace 
*ftrace)
return 0;
 }
 
+static int set_tracing_funcgraph_irqs(struct perf_ftrace *ftrace)
+{
+   if (!ftrace->graph_noirqs)
+   return 0;
+
+   if (write_tracing_option_file("funcgraph-irqs", "0") < 0)
+   return -1;
+
+   return 0;
+}
+
 static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
**argv)
 {
char *trace_file;
@@ -481,6 +494,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
goto out_reset;
}
 
+   if (set_tracing_funcgraph_irqs(ftrace) < 0) {
+   pr_err("failed to set tracing option funcgraph-irqs\n");
+   goto out_reset;
+   }
+
if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
goto out_reset;
@@ -661,6 +679,7 @@ static int parse_graph_tracer_opts(const struct option *opt,
struct perf_ftrace *ftrace = (struct perf_ftrace *) opt->value;
struct sublevel_option graph_tracer_opts[] = {
{ .name = "nosleep-time",   .value_ptr = 
&ftrace->graph_nosleep_time },
+   { .name = "noirqs", .value_ptr = 
&ftrace->graph_noirqs },
{ .name = NULL, }
};
 
@@ -715,7 +734,7 @@ int cmd_ftrace(int argc, const char **argv)
OPT_INTEGER('D', "graph-depth", &ftrace.graph_depth,
"Max depth for function graph tracer"),
OPT_CALLBACK(0, "graph-opts", &ftrace, "options",
-"graph tracer options, available options: nosleep-time",
+"graph tracer options, available options: 
nosleep-time,noirqs",
 parse_graph_tracer_opts),
OPT_CALLBACK('m', "buffer-size", &ftrace.percpu_buffer_size, "size",
 "size of per cpu buffer", parse_buffer_size),
-- 
2.25.1



[PATCH v7 03/18] perf ftrace: factor out function write_tracing_file_int()

2020-07-17 Thread Changbin Du
We will reuse this function later.

Signed-off-by: Changbin Du 
---
 tools/perf/builtin-ftrace.c | 17 -
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 3c0e60fdfe0f..9abf97c29cb6 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -168,6 +168,17 @@ static int read_tracing_file_to_stdout(const char *name)
return ret;
 }
 
+static int write_tracing_file_int(const char *name, int value)
+{
+   char buf[16];
+
+   snprintf(buf, sizeof(buf), "%d", value);
+   if (write_tracing_file(name, buf) < 0)
+   return -1;
+
+   return 0;
+}
+
 static int reset_tracing_cpu(void);
 static void reset_tracing_filters(void);
 
@@ -298,8 +309,6 @@ static void reset_tracing_filters(void)
 
 static int set_tracing_depth(struct perf_ftrace *ftrace)
 {
-   char buf[16];
-
if (ftrace->graph_depth == 0)
return 0;
 
@@ -308,9 +317,7 @@ static int set_tracing_depth(struct perf_ftrace *ftrace)
return -1;
}
 
-   snprintf(buf, sizeof(buf), "%d", ftrace->graph_depth);
-
-   if (write_tracing_file("max_graph_depth", buf) < 0)
+   if (write_tracing_file_int("max_graph_depth", ftrace->graph_depth) < 0)
return -1;
 
return 0;
-- 
2.25.1



[PATCH v7 04/18] perf ftrace: add option '-m/--buffer-size' to set per-cpu buffer size

2020-07-17 Thread Changbin Du
This adds an option '-m/--buffer-size' to allow us set the size of per-cpu
tracing buffer.

Signed-off-by: Changbin Du 

---
v2: support units as a suffix.
---
 tools/perf/Documentation/perf-ftrace.txt |  5 +++
 tools/perf/builtin-ftrace.c  | 56 +++-
 2 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index d79560dea19f..dcac0d75a0e5 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -52,6 +52,11 @@ OPTIONS
Ranges of CPUs are specified with -: 0-2.
Default is to trace on all online CPUs.
 
+-m::
+--buffer-size::
+   Set the size of per-cpu tracing buffer,  is expected to
+   be a number with appended unit character - B/K/M/G.
+
 -T::
 --trace-funcs=::
Only trace functions given by the argument.  Multiple functions
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 9abf97c29cb6..3ea3aaa4650b 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -26,7 +26,7 @@
 #include "thread_map.h"
 #include "util/cap.h"
 #include "util/config.h"
-
+#include "util/units.h"
 
 struct perf_ftrace {
struct evlist   *evlist;
@@ -38,6 +38,7 @@ struct perf_ftrace {
struct list_headgraph_funcs;
struct list_headnograph_funcs;
int graph_depth;
+   unsigned long   percpu_buffer_size;
 };
 
 struct filter_entry {
@@ -323,6 +324,21 @@ static int set_tracing_depth(struct perf_ftrace *ftrace)
return 0;
 }
 
+static int set_tracing_percpu_buffer_size(struct perf_ftrace *ftrace)
+{
+   int ret;
+
+   if (ftrace->percpu_buffer_size == 0)
+   return 0;
+
+   ret = write_tracing_file_int("buffer_size_kb",
+ftrace->percpu_buffer_size / 1024);
+   if (ret < 0)
+   return ret;
+
+   return 0;
+}
+
 static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
**argv)
 {
char *trace_file;
@@ -387,6 +403,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
goto out_reset;
}
 
+   if (set_tracing_percpu_buffer_size(ftrace) < 0) {
+   pr_err("failed to set tracing per-cpu buffer size\n");
+   goto out_reset;
+   }
+
if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
goto out_reset;
@@ -506,6 +527,37 @@ static void delete_filter_func(struct list_head *head)
}
 }
 
+static int parse_buffer_size(const struct option *opt,
+const char *str, int unset)
+{
+   unsigned long *s = (unsigned long *)opt->value;
+   static struct parse_tag tags_size[] = {
+   { .tag  = 'B', .mult = 1   },
+   { .tag  = 'K', .mult = 1 << 10 },
+   { .tag  = 'M', .mult = 1 << 20 },
+   { .tag  = 'G', .mult = 1 << 30 },
+   { .tag  = 0 },
+   };
+   unsigned long val;
+
+   if (unset) {
+   *s = 0;
+   return 0;
+   }
+
+   val = parse_tag_value(str, tags_size);
+   if (val != (unsigned long) -1) {
+   if (val < 1024) {
+   pr_err("buffer size too small, must larger than 1KB.");
+   return -1;
+   }
+   *s = val;
+   return 0;
+   }
+
+   return -1;
+}
+
 int cmd_ftrace(int argc, const char **argv)
 {
int ret;
@@ -543,6 +595,8 @@ int cmd_ftrace(int argc, const char **argv)
 "Set nograph filter on given functions", 
parse_filter_func),
OPT_INTEGER('D', "graph-depth", &ftrace.graph_depth,
"Max depth for function graph tracer"),
+   OPT_CALLBACK('m', "buffer-size", &ftrace.percpu_buffer_size, "size",
+"size of per cpu buffer", parse_buffer_size),
OPT_END()
};
 
-- 
2.25.1



[PATCH v7 02/18] perf ftrace: add option '-F/--funcs' to list available functions

2020-07-17 Thread Changbin Du
This adds an option '-F/--funcs' to list all available functions to trace,
which is read from tracing file 'available_filter_functions'.

$ sudo ./perf ftrace -F | head
trace_initcall_finish_cb
initcall_blacklisted
do_one_initcall
do_one_initcall
trace_initcall_start_cb
run_init_process
try_to_run_init_process
match_dev_by_label
match_dev_by_uuid
rootfs_init_fs_context

Signed-off-by: Changbin Du 

---
v3: fix return value issue.
v2: option name '-l/--list-functions' -> '-F/--funcs'
---
 tools/perf/Documentation/perf-ftrace.txt |  4 +++
 tools/perf/builtin-ftrace.c  | 46 
 2 files changed, 50 insertions(+)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 952e46669168..d79560dea19f 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -30,6 +30,10 @@ OPTIONS
 --verbose=::
 Verbosity level.
 
+-F::
+--funcs::
+List all available functions to trace.
+
 -p::
 --pid=::
Trace on existing process id (comma separated list).
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 5f53da87040d..3c0e60fdfe0f 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -32,6 +32,7 @@ struct perf_ftrace {
struct evlist   *evlist;
struct target   target;
const char  *tracer;
+   boollist_avail_functions;
struct list_headfilters;
struct list_headnotrace;
struct list_headgraph_funcs;
@@ -127,6 +128,46 @@ static int append_tracing_file(const char *name, const 
char *val)
return __write_tracing_file(name, val, true);
 }
 
+static int read_tracing_file_to_stdout(const char *name)
+{
+   char buf[4096];
+   char *file;
+   int fd;
+   int ret = -1;
+
+   file = get_tracing_file(name);
+   if (!file) {
+   pr_debug("cannot get tracing file: %s\n", name);
+   return -1;
+   }
+
+   fd = open(file, O_RDONLY);
+   if (fd < 0) {
+   pr_debug("cannot open tracing file: %s: %s\n",
+name, str_error_r(errno, buf, sizeof(buf)));
+   goto out;
+   }
+
+   /* read contents to stdout */
+   while (true) {
+   int n = read(fd, buf, sizeof(buf));
+   if (n == 0)
+   break;
+   else if (n < 0)
+   goto out_close;
+
+   if (fwrite(buf, n, 1, stdout) != 1)
+   goto out_close;
+   }
+   ret = 0;
+
+out_close:
+   close(fd);
+out:
+   put_tracing_file(file);
+   return ret;
+}
+
 static int reset_tracing_cpu(void);
 static void reset_tracing_filters(void);
 
@@ -301,6 +342,9 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
signal(SIGCHLD, sig_handler);
signal(SIGPIPE, sig_handler);
 
+   if (ftrace->list_avail_functions)
+   return 
read_tracing_file_to_stdout("available_filter_functions");
+
if (reset_tracing_files(ftrace) < 0) {
pr_err("failed to reset ftrace\n");
goto out;
@@ -470,6 +514,8 @@ int cmd_ftrace(int argc, const char **argv)
const struct option ftrace_options[] = {
OPT_STRING('t', "tracer", &ftrace.tracer, "tracer",
   "tracer to use: function or function_graph (This option is 
deprecated)"),
+   OPT_BOOLEAN('F', "funcs", &ftrace.list_avail_functions,
+   "Show available functions to filter"),
OPT_STRING('p', "pid", &ftrace.target.pid, "pid",
   "trace on existing process id"),
OPT_INCR('v', "verbose", &verbose,
-- 
2.25.1



[PATCH v7 05/18] perf ftrace: show trace column header

2020-07-17 Thread Changbin Du
This makes perf-ftrace display column header before printing trace.

  $ sudo perf ftrace
  # tracer: function
  #
  # entries-in-buffer/entries-written: 0/0   #P:8
  #
  #TASK-PID CPU#   TIMESTAMP  FUNCTION
  #  | | |   | |
 <...>-9246  [006]  10726.262760: mutex_unlock <-rb_simple_write
 <...>-9246  [006]  10726.262764: __fsnotify_parent <-vfs_write
 <...>-9246  [006]  10726.262765: fsnotify <-vfs_write
 <...>-9246  [006]  10726.262766: __sb_end_write <-vfs_write
 <...>-9246  [006]  10726.262767: fpregs_assert_state_consistent 
<-do_syscall_64

Signed-off-by: Changbin Du 
---
 tools/perf/builtin-ftrace.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 3ea3aaa4650b..6ce626a2d0d1 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -433,6 +433,9 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
fcntl(trace_fd, F_SETFL, O_NONBLOCK);
pollfd.fd = trace_fd;
 
+   /* display column headers */
+   read_tracing_file_to_stdout("trace");
+
if (write_tracing_file("tracing_on", "1") < 0) {
pr_err("can't enable tracing\n");
goto out_close_fd;
-- 
2.25.1



[PATCH v7 01/18] perf ftrace: select function/function_graph tracer automatically

2020-07-17 Thread Changbin Du
The '-g/-G' options have already implied function_graph tracer should be
used instead of function tracer. So the extra option '--tracer' can be
killed.

This patch changes the behavior as below:
  - By default, function tracer is used.
  - If '-g' or '-G' option is on, then function_graph tracer is used.
  - The perf configuration item 'ftrace.tracer' is marked as deprecated.
  - The option '--tracer' is marked as deprecated.

Here are some examples.

This will start tracing all functions using function tracer:
  $ sudo perf ftrace

This will trace all functions using function graph tracer:
  $ sudo perf ftrace -G '*'

This will trace function vfs_read using function graph tracer:
  $ sudo perf ftrace -G vfs_read

Signed-off-by: Changbin Du 

---
v3: remove default '*' for -G/-T.
---
 tools/perf/Documentation/perf-config.txt |  5 -
 tools/perf/Documentation/perf-ftrace.txt |  2 +-
 tools/perf/builtin-ftrace.c  | 15 ++-
 3 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/tools/perf/Documentation/perf-config.txt 
b/tools/perf/Documentation/perf-config.txt
index c7d3df5798e2..a25fee7de3b2 100644
--- a/tools/perf/Documentation/perf-config.txt
+++ b/tools/perf/Documentation/perf-config.txt
@@ -612,11 +612,6 @@ trace.*::
"libbeauty", the default, to use the same argument beautifiers 
used in the
strace-like sys_enter+sys_exit lines.
 
-ftrace.*::
-   ftrace.tracer::
-   Can be used to select the default tracer. Possible values are
-   'function' and 'function_graph'.
-
 llvm.*::
llvm.clang-path::
Path to clang. If omit, search it from $PATH.
diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index b80c84307dc9..952e46669168 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -24,7 +24,7 @@ OPTIONS
 
 -t::
 --tracer=::
-   Tracer to use: function_graph or function.
+   Tracer to use: function_graph or function. This option is deprecated.
 
 -v::
 --verbose=::
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 2bfc1b0db536..5f53da87040d 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -27,7 +27,6 @@
 #include "util/cap.h"
 #include "util/config.h"
 
-#define DEFAULT_TRACER  "function_graph"
 
 struct perf_ftrace {
struct evlist   *evlist;
@@ -419,6 +418,7 @@ static int perf_ftrace_config(const char *var, const char 
*value, void *cb)
if (strcmp(var, "ftrace.tracer"))
return -1;
 
+   pr_warning("Configuration ftrace.tracer is deprecated\n");
if (!strcmp(value, "function_graph") ||
!strcmp(value, "function")) {
ftrace->tracer = value;
@@ -459,7 +459,7 @@ int cmd_ftrace(int argc, const char **argv)
 {
int ret;
struct perf_ftrace ftrace = {
-   .tracer = DEFAULT_TRACER,
+   .tracer = "function",
.target = { .uid = UINT_MAX, },
};
const char * const ftrace_usage[] = {
@@ -469,7 +469,7 @@ int cmd_ftrace(int argc, const char **argv)
};
const struct option ftrace_options[] = {
OPT_STRING('t', "tracer", &ftrace.tracer, "tracer",
-  "tracer to use: function_graph(default) or function"),
+  "tracer to use: function or function_graph (This option is 
deprecated)"),
OPT_STRING('p', "pid", &ftrace.target.pid, "pid",
   "trace on existing process id"),
OPT_INCR('v', "verbose", &verbose,
@@ -479,11 +479,13 @@ int cmd_ftrace(int argc, const char **argv)
OPT_STRING('C', "cpu", &ftrace.target.cpu_list, "cpu",
"list of cpus to monitor"),
OPT_CALLBACK('T', "trace-funcs", &ftrace.filters, "func",
-"trace given functions only", parse_filter_func),
+"trace given functions using function tracer",
+parse_filter_func),
OPT_CALLBACK('N', "notrace-funcs", &ftrace.notrace, "func",
 "do not trace given functions", parse_filter_func),
OPT_CALLBACK('G', "graph-funcs", &ftrace.graph_funcs, "func",
-"Set graph filter on given functions", parse_filter_func),
+"trace given functions using function_graph tracer",
+parse_filter_func),
  

[PATCH v7 00/18] perf: ftrace enhancement

2020-07-17 Thread Changbin Du
The perf has basic kernel ftrace support but lack support of most tracing
options. This serias is target to enhance the perf ftrace functionality so
that we can make full use of kernel ftrace with perf.

In general, this serias be cataloged into two main changes:
  1) Improve usability of existing functions. For example, we don't need to type
 extra option to select the tracer.
  2) Add new options to support all other ftrace functions.

Here is a glance of all ftrace functions with this serias:

$ sudo perf ftrace -h

 Usage: perf ftrace [] []
or: perf ftrace [] --  []

-a, --all-cpussystem-wide collection from all CPUs
-C, --cpulist of cpus to monitor
-D, --delayms to wait before starting tracing after program start
-F, --funcs   Show available functions to filter
-G, --graph-funcs 
  trace given functions using function_graph tracer
-g, --nograph-funcs 
  Set nograph filter on given functions
-m, --buffer-size 
  size of per cpu buffer
-N, --notrace-funcs 
  do not trace given functions
-p, --pidtrace on existing process id
-T, --trace-funcs 
  trace given functions using function tracer
-t, --tracer 
  tracer to use: function or function_graph (This 
option is deprecated)
-v, --verbose be more verbose
--func-opts 
  function tracer options, available options: 
call-graph,irq-info
--graph-opts 
  graph tracer options, available options: 
nosleep-time,noirqs,verbose,thresh=,depth=
--inherit trace children processes
--tidtrace on existing thread id (exclusive to --pid)

v7:
  o add back '--tid '.
v6:
  o fix return value of read_tracing_file_to_stdout().
  o make __cmd_ftrace() shorter.
  o remove option '-t, --tid '.
v5:
  o trivial fixes.
v4:
  o add util/parse-sublevel-options.c
  O remove -D/--graph-depth
v3:
  o add --func-opts and --graph-opts to set tracer specific options.
  o support units as a suffix for option '-m/--buffer-size'.
v2:
  o patches for option '-u/--userstacktrace' and '--no-pager' are dropped.
  o update all related perf documentation.
  o rename some options. Now all funcgraph tracer options are prefixed with
'--graph-', while all function tracer options are prefixed with '--func-'.
  o mark old options deprecated instead of removing them.


Changbin Du (18):
  perf ftrace: select function/function_graph tracer automatically
  perf ftrace: add option '-F/--funcs' to list available functions
  perf ftrace: factor out function write_tracing_file_int()
  perf ftrace: add option '-m/--buffer-size' to set per-cpu buffer size
  perf ftrace: show trace column header
  perf ftrace: add option '--inherit' to trace children processes
  perf: util: add general function to parse sublevel options
  perf ftrace: add support for tracing option 'func_stack_trace'
  perf ftrace: add support for trace option sleep-time
  perf ftrace: add support for trace option funcgraph-irqs
  perf ftrace: add support for tracing option 'irq-info'
  perf ftrace: add option 'verbose' to show more info for graph tracer
  perf ftrace: add support for trace option tracing_thresh
  perf: ftrace: allow set graph depth by '--graph-opts'
  perf ftrace: add option -D/--delay to delay tracing
  perf ftrace: add option --tid to filter by thread id
  perf: ftrace: Add set_tracing_options() to set all trace options
  perf ftrace: add change log

 tools/perf/Documentation/perf-config.txt |   5 -
 tools/perf/Documentation/perf-ftrace.txt |  36 +-
 tools/perf/builtin-ftrace.c  | 415 +--
 tools/perf/util/Build|   1 +
 tools/perf/util/debug.c  |  61 +---
 tools/perf/util/parse-sublevel-options.c |  70 
 tools/perf/util/parse-sublevel-options.h |  11 +
 7 files changed, 513 insertions(+), 86 deletions(-)
 create mode 100644 tools/perf/util/parse-sublevel-options.c
 create mode 100644 tools/perf/util/parse-sublevel-options.h

-- 
2.25.1



Re: [PATCH v5 03/17] perf ftrace: add option -t/--tid to filter by thread id

2020-07-17 Thread Changbin Du
On Fri, Jul 17, 2020 at 01:01:24PM -0400, Steven Rostedt wrote:
> On Fri, 17 Jul 2020 21:26:50 +0800
> Changbin Du  wrote:
> 
> > On Thu, Jul 16, 2020 at 12:36:30PM -0300, Arnaldo Carvalho de Melo wrote:
> > > Em Sat, Jul 11, 2020 at 08:40:21PM +0800, Changbin Du escreveu:  
> > > > This allows us to trace single thread instead of the whole process.
> > > > 
> > > > Signed-off-by: Changbin Du 
> > > > ---
> > > >  tools/perf/Documentation/perf-ftrace.txt | 4 
> > > >  tools/perf/builtin-ftrace.c  | 2 ++
> > > >  2 files changed, 6 insertions(+)
> > > > 
> > > > diff --git a/tools/perf/Documentation/perf-ftrace.txt 
> > > > b/tools/perf/Documentation/perf-ftrace.txt
> > > > index d79560dea19f..e204bf6d50d8 100644
> > > > --- a/tools/perf/Documentation/perf-ftrace.txt
> > > > +++ b/tools/perf/Documentation/perf-ftrace.txt
> > > > @@ -38,6 +38,10 @@ OPTIONS
> > > >  --pid=::
> > > > Trace on existing process id (comma separated list).
> > > >  
> > > > +-t::
> > > > +--tid=::
> > > > +   Trace on existing thread id (comma separated list).
> > > > +  
> > > 
> > > 
> > > Humm, I just  tried:
> > > 
> > > [root@five ~]# yes > /dev/null &
> > > [1] 18265
> > > [root@five ~]# perf ftrace --tid 18265
> > > ^C[root@five ~]#
> > > 
> > > After waiting for a while, nothing, what am I doing wrong?
> > >  
> > I got it wrong. Currently ftrace only can filter by pid. If the pid is not
> > the main thread it won't work.
> 
> Wait what?
> 
> The "pid" for ftrace is really a "task id" which is a thread id.
>
My bad. I traced a sleeping thread yesterday so no event generated.

Now it works:
$ pstree -p 2378
qemu-system-x86(2378)─┬─{qemu-system-x86}(2379)
  ├─{qemu-system-x86}(2382)
  ├─{qemu-system-x86}(2385)
  ├─{qemu-system-x86}(2387)
  ├─{qemu-system-x86}(2388)
  ├─{qemu-system-x86}(2389)
  ├─{qemu-system-x86}(2390)
  ├─{qemu-system-x86}(2391)
  ├─{qemu-system-x86}(2392)
$ sudo ./perf ftrace --tid 2388
[sudo] password for changbin:
# tracer: function
#
# entries-in-buffer/entries-written: 0/0   #P:8
#
#   TASK-PID CPU#   TIMESTAMP  FUNCTION
#  | | |   | |
  -0 [001]   6561.553989: switch_mm_irqs_off <-__schedule
  -0 [001]   6561.553996: load_new_mm_cr3 <-switch_mm_irqs_off
 qemu-system-x86-2388  [001]   6561.553997: finish_task_switch <-__schedule
 qemu-system-x86-2388  [001]   6561.553998: smp_irq_work_interrupt 
<-irq_work_interrupt
 qemu-system-x86-2388  [001]   6561.553999: irq_enter <-smp_irq_work_interrupt
 qemu-system-x86-2388  [001]   6561.553999: rcu_irq_enter <-irq_enter
 qemu-system-x86-2388  [001]   6561.554000: __wake_up <-rb_wake_up_waiters
 qemu-system-x86-2388  [001]   6561.554000: __wake_up_common_lock <-__wake_up
 qemu-system-x86-2388  [001]   6561.554000: _raw_spin_lock_irqsave 
<-__wake_up_common_lock
 qemu-system-x86-2388  [001]   6561.554000: __wake_up_common 
<-__wake_up_common_lock
 ...
> [root@bxtest ~]# yes > /dev/null &
> [1] 6799
> [root@bxtest ~]# trace-cmd record -e all -P 6799
> Hit Ctrl^C to stop recording
> ^CCPU 0: 3573031 events lost
> CPU0 data recorded at offset=0x838000
> 627675136 bytes in size
> CPU1 data recorded at offset=0x25ed1000
> 0 bytes in size
> CPU2 data recorded at offset=0x25ed1000
> 0 bytes in size
> CPU3 data recorded at offset=0x25ed1000
> 0 bytes in size
> CPU4 data recorded at offset=0x25ed1000
> 0 bytes in size
> CPU5 data recorded at offset=0x25ed1000
> 0 bytes in size
> CPU6 data recorded at offset=0x25ed1000
> 0 bytes in size
> CPU7 data recorded at offset=0x25ed1000
> 0 bytes in size
> [root@bxtest ~]# trace-cmd report | head 
> CPU 1 is empty
> CPU 2 is empty
> CPU 3 is empty
> CPU 4 is empty
> CPU 5 is empty
> CPU 6 is empty
> CPU 7 is empty
> cpus=8
>  yes-6799  [000] 67825.580902: sys_exit: NR 1 = 8192
>  yes-6799  [000] 67825.580903: sys_exit_write:   0x2000
> 
> 
> What's different about tid vs pid?
> 
> -- Steve
> 
> 
> 
> > 
> > So this patch makes no sense. will drop this.
> > 

-- 
Cheers,
Changbin Du


[PATCH v6 12/17] perf ftrace: add option 'verbose' to show more info for graph tracer

2020-07-17 Thread Changbin Du
Sometimes we want ftrace display more and longer information about
the trace.

$ sudo perf ftrace -G '*'
 2)   0.979 us|  mutex_unlock();
 2)   1.540 us|  __fsnotify_parent();
 2)   0.433 us|  fsnotify();

$ sudo perf ftrace -G '*' --graph-opts verbose
14160.770883 |   0)  <...>-47814   |   |   1.289 us|  mutex_unlock();
14160.770886 |   0)  <...>-47814   |   |   1.624 us|  
__fsnotify_parent();
14160.770887 |   0)  <...>-47814   |   |   0.636 us|  fsnotify();
14160.770888 |   0)  <...>-47814   |   |   0.328 us|  __sb_end_write();
14160.770888 |   0)  <...>-47814   |  d... |   0.430 us|  
fpregs_assert_state_consistent();
14160.770889 |   0)  <...>-47814   |  d... |   |  do_syscall_64() {
14160.770889 |   0)  <...>-47814   |  .... |       |
__x64_sys_close() {

Signed-off-by: Changbin Du 
---
 tools/perf/Documentation/perf-ftrace.txt |  1 +
 tools/perf/builtin-ftrace.c  | 29 +++-
 2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 3ab1fe040994..319ec6375228 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -103,6 +103,7 @@ OPTIONS
List of options allowed to set:
  nosleep-time - Measure on-CPU time only for function_graph tracer.
  noirqs   - Ignore functions that happen inside interrupt.
+ verbose  - Show process names, PIDs, timestamps, etc.
 
 SEE ALSO
 
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 95d87c5966ad..0d893d97691d 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -45,6 +45,7 @@ struct perf_ftrace {
int func_irq_info;
int graph_nosleep_time;
int graph_noirqs;
+   int graph_verbose;
 };
 
 struct filter_entry {
@@ -208,6 +209,9 @@ static void reset_tracing_options(struct perf_ftrace 
*ftrace __maybe_unused)
write_tracing_option_file("func_stack_trace", "0");
write_tracing_option_file("sleep-time", "1");
write_tracing_option_file("funcgraph-irqs", "1");
+   write_tracing_option_file("funcgraph-proc", "0");
+   write_tracing_option_file("funcgraph-abstime", "0");
+   write_tracing_option_file("latency-format", "0");
write_tracing_option_file("irq-info", "0");
 }
 
@@ -423,6 +427,23 @@ static int set_tracing_funcgraph_irqs(struct perf_ftrace 
*ftrace)
return 0;
 }
 
+static int set_tracing_funcgraph_verbose(struct perf_ftrace *ftrace)
+{
+   if (!ftrace->graph_verbose)
+   return 0;
+
+   if (write_tracing_option_file("funcgraph-proc", "1") < 0)
+   return -1;
+
+   if (write_tracing_option_file("funcgraph-abstime", "1") < 0)
+   return -1;
+
+   if (write_tracing_option_file("latency-format", "1") < 0)
+   return -1;
+
+   return 0;
+}
+
 static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
**argv)
 {
char *trace_file;
@@ -517,6 +538,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
goto out_reset;
}
 
+   if (set_tracing_funcgraph_verbose(ftrace) < 0) {
+   pr_err("failed to set tracing option 
funcgraph-proc/funcgraph-abstime\n");
+   goto out_reset;
+   }
+
if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
goto out_reset;
@@ -699,6 +725,7 @@ static int parse_graph_tracer_opts(const struct option *opt,
struct sublevel_option graph_tracer_opts[] = {
{ .name = "nosleep-time",   .value_ptr = 
&ftrace->graph_nosleep_time },
{ .name = "noirqs", .value_ptr = 
&ftrace->graph_noirqs },
+   { .name = "verbose",.value_ptr = 
&ftrace->graph_verbose },
{ .name = NULL, }
};
 
@@ -753,7 +780,7 @@ int cmd_ftrace(int argc, const char **argv)
OPT_INTEGER('D', "graph-depth", &ftrace.graph_depth,
"Max depth for function graph tracer"),
OPT_CALLBACK(0, "graph-opts", &ftrace, "options",
-"graph tracer options, available options: 
nosleep-time,noirqs",
+"graph tracer options, available options: 
nosleep-time,noirqs,verbose",
 parse_graph_tracer_opts),
OPT_CALLBACK('m', "buffer-size", &ftrace.percpu_buffer_size, "size",
 "size of per cpu buffer", parse_buffer_size),
-- 
2.25.1



[PATCH v6 13/17] perf ftrace: add support for trace option tracing_thresh

2020-07-17 Thread Changbin Du
This adds an option '--graph-opts thresh' to setup trace duration
threshold for funcgraph tracer.

$ sudo ./perf ftrace -G '*' --graph-opts thresh=100
 3) ! 184.060 us  |} /* schedule */
 3) ! 185.600 us  |  } /* exit_to_usermode_loop */
 2) ! 225.989 us  |} /* schedule_idle */
 2) # 4140.051 us |  } /* do_idle */

Signed-off-by: Changbin Du 
---
 tools/perf/Documentation/perf-ftrace.txt |  1 +
 tools/perf/builtin-ftrace.c  | 26 +++-
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 319ec6375228..96e5e8d7f65c 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -104,6 +104,7 @@ OPTIONS
  nosleep-time - Measure on-CPU time only for function_graph tracer.
  noirqs   - Ignore functions that happen inside interrupt.
  verbose  - Show process names, PIDs, timestamps, etc.
+ thresh=   - Setup trace duration threshold in microseconds.
 
 SEE ALSO
 
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 0d893d97691d..5d948239bd70 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -46,6 +46,7 @@ struct perf_ftrace {
int graph_nosleep_time;
int graph_noirqs;
int graph_verbose;
+   int graph_thresh;
 };
 
 struct filter_entry {
@@ -232,6 +233,9 @@ static int reset_tracing_files(struct perf_ftrace *ftrace 
__maybe_unused)
if (write_tracing_file("max_graph_depth", "0") < 0)
return -1;
 
+   if (write_tracing_file("tracing_thresh", "0") < 0)
+   return -1;
+
reset_tracing_filters();
reset_tracing_options(ftrace);
return 0;
@@ -444,6 +448,20 @@ static int set_tracing_funcgraph_verbose(struct 
perf_ftrace *ftrace)
return 0;
 }
 
+static int set_tracing_thresh(struct perf_ftrace *ftrace)
+{
+   int ret;
+
+   if (ftrace->graph_thresh == 0)
+   return 0;
+
+   ret = write_tracing_file_int("tracing_thresh", ftrace->graph_thresh);
+   if (ret < 0)
+   return ret;
+
+   return 0;
+}
+
 static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
**argv)
 {
char *trace_file;
@@ -543,6 +561,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
goto out_reset;
}
 
+   if (set_tracing_thresh(ftrace) < 0) {
+   pr_err("failed to set tracing thresh\n");
+   goto out_reset;
+   }
+
if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
goto out_reset;
@@ -726,6 +749,7 @@ static int parse_graph_tracer_opts(const struct option *opt,
{ .name = "nosleep-time",   .value_ptr = 
&ftrace->graph_nosleep_time },
{ .name = "noirqs", .value_ptr = 
&ftrace->graph_noirqs },
{ .name = "verbose",.value_ptr = 
&ftrace->graph_verbose },
+   { .name = "thresh", .value_ptr = 
&ftrace->graph_thresh },
{ .name = NULL, }
};
 
@@ -780,7 +804,7 @@ int cmd_ftrace(int argc, const char **argv)
OPT_INTEGER('D', "graph-depth", &ftrace.graph_depth,
"Max depth for function graph tracer"),
OPT_CALLBACK(0, "graph-opts", &ftrace, "options",
-"graph tracer options, available options: 
nosleep-time,noirqs,verbose",
+"graph tracer options, available options: 
nosleep-time,noirqs,verbose,thresh=",
 parse_graph_tracer_opts),
OPT_CALLBACK('m', "buffer-size", &ftrace.percpu_buffer_size, "size",
 "size of per cpu buffer", parse_buffer_size),
-- 
2.25.1



[PATCH v6 14/17] perf: ftrace: allow set graph depth by '--graph-opts'

2020-07-17 Thread Changbin Du
This is to have a consistent view of all graph tracer options.
The original option '--graph-depth' is marked as deprecated.

Signed-off-by: Changbin Du 
---
 tools/perf/Documentation/perf-ftrace.txt | 5 +
 tools/perf/builtin-ftrace.c  | 5 ++---
 2 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 96e5e8d7f65c..6f17939b8789 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -95,16 +95,13 @@ OPTIONS
This can be used more than once to specify multiple functions.
It will be passed to 'set_graph_notrace' in tracefs.
 
--D::
---graph-depth=::
-   Set max depth for function graph tracer to follow
-
 --graph-opts::
List of options allowed to set:
  nosleep-time - Measure on-CPU time only for function_graph tracer.
  noirqs   - Ignore functions that happen inside interrupt.
  verbose  - Show process names, PIDs, timestamps, etc.
  thresh=   - Setup trace duration threshold in microseconds.
+ depth=- Set max depth for function graph tracer to follow.
 
 SEE ALSO
 
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 5d948239bd70..3ddd7568b456 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -750,6 +750,7 @@ static int parse_graph_tracer_opts(const struct option *opt,
{ .name = "noirqs", .value_ptr = 
&ftrace->graph_noirqs },
{ .name = "verbose",.value_ptr = 
&ftrace->graph_verbose },
{ .name = "thresh", .value_ptr = 
&ftrace->graph_thresh },
+   { .name = "depth",  .value_ptr = 
&ftrace->graph_depth },
{ .name = NULL, }
};
 
@@ -801,10 +802,8 @@ int cmd_ftrace(int argc, const char **argv)
 parse_filter_func),
OPT_CALLBACK('g', "nograph-funcs", &ftrace.nograph_funcs, "func",
 "Set nograph filter on given functions", 
parse_filter_func),
-   OPT_INTEGER('D', "graph-depth", &ftrace.graph_depth,
-   "Max depth for function graph tracer"),
OPT_CALLBACK(0, "graph-opts", &ftrace, "options",
-"graph tracer options, available options: 
nosleep-time,noirqs,verbose,thresh=",
+"graph tracer options, available options: 
nosleep-time,noirqs,verbose,thresh=,depth=",
 parse_graph_tracer_opts),
OPT_CALLBACK('m', "buffer-size", &ftrace.percpu_buffer_size, "size",
 "size of per cpu buffer", parse_buffer_size),
-- 
2.25.1



[PATCH v6 16/17] perf: ftrace: Add set_tracing_options() to set all trace options

2020-07-17 Thread Changbin Du
Now the __cmd_ftrace() becomes a bit long. This moves the trace
option setting code to a separate function set_tracing_options().

Suggested-by: Namhyung Kim 
Signed-off-by: Changbin Du 
---
 tools/perf/builtin-ftrace.c | 118 +++-
 1 file changed, 63 insertions(+), 55 deletions(-)

diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 64b68331048a..edf307f7d716 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -463,110 +463,118 @@ static int set_tracing_thresh(struct perf_ftrace 
*ftrace)
return 0;
 }
 
-static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
**argv)
+static int set_tracing_options(struct perf_ftrace *ftrace)
 {
-   char *trace_file;
-   int trace_fd;
-   char buf[4096];
-   struct pollfd pollfd = {
-   .events = POLLIN,
-   };
-
-   if (!(perf_cap__capable(CAP_PERFMON) ||
- perf_cap__capable(CAP_SYS_ADMIN))) {
-   pr_err("ftrace only works for %s!\n",
-#ifdef HAVE_LIBCAP_SUPPORT
-   "users with the CAP_PERFMON or CAP_SYS_ADMIN capability"
-#else
-   "root"
-#endif
-   );
-   return -1;
-   }
-
-   signal(SIGINT, sig_handler);
-   signal(SIGUSR1, sig_handler);
-   signal(SIGCHLD, sig_handler);
-   signal(SIGPIPE, sig_handler);
-
-   if (ftrace->list_avail_functions)
-   return 
read_tracing_file_to_stdout("available_filter_functions");
-
-   if (reset_tracing_files(ftrace) < 0) {
-   pr_err("failed to reset ftrace\n");
-   goto out;
-   }
-
-   /* reset ftrace buffer */
-   if (write_tracing_file("trace", "0") < 0)
-   goto out;
-
-   if (argc && perf_evlist__prepare_workload(ftrace->evlist,
-   &ftrace->target, argv, false,
-   ftrace__workload_exec_failed_signal) < 0) {
-   goto out;
-   }
-
if (set_tracing_pid(ftrace) < 0) {
pr_err("failed to set ftrace pid\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_cpu(ftrace) < 0) {
pr_err("failed to set tracing cpumask\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_func_stack_trace(ftrace) < 0) {
pr_err("failed to set tracing option func_stack_trace\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_func_irqinfo(ftrace) < 0) {
pr_err("failed to set tracing option irq-info\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_filters(ftrace) < 0) {
pr_err("failed to set tracing filters\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_depth(ftrace) < 0) {
pr_err("failed to set graph depth\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_percpu_buffer_size(ftrace) < 0) {
pr_err("failed to set tracing per-cpu buffer size\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_trace_inherit(ftrace) < 0) {
pr_err("failed to set tracing option function-fork\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_sleep_time(ftrace) < 0) {
pr_err("failed to set tracing option sleep-time\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_funcgraph_irqs(ftrace) < 0) {
pr_err("failed to set tracing option funcgraph-irqs\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_funcgraph_verbose(ftrace) < 0) {
pr_err("failed to set tracing option 
funcgraph-proc/funcgraph-abstime\n");
-   goto out_reset;
+   return -1;
}
 
if (set_tracing_thresh(ftrace) < 0) {
pr_err("failed to set tracing thresh\n");
-   goto out_reset;
+   return -1;
+   }
+
+   return 0;
+}
+
+static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
**argv)
+{
+   char *trace_file;
+   int trace_fd;
+   char buf[4096];
+   struct pollfd pollfd = {
+   .events = POLLIN,
+   };
+
+   if (!(perf_cap__capable(CAP_PERFMON) ||
+ perf_cap__capable(CAP_SYS_ADMIN))) {
+   pr_err("ftrace only works for %s!\n",
+#ifdef HAVE_LIBCAP_SUPPORT

[PATCH v6 15/17] perf ftrace: add option -D/--delay to delay tracing

2020-07-17 Thread Changbin Du
This adds an option '-D/--delay' to allow us to start tracing some
times later after workload is launched.

Signed-off-by: Changbin Du 
---
 tools/perf/Documentation/perf-ftrace.txt |  4 
 tools/perf/builtin-ftrace.c  | 19 ---
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 6f17939b8789..077249c979f2 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -38,6 +38,10 @@ OPTIONS
 --pid=::
Trace on existing process id (comma separated list).
 
+-D::
+--delay::
+   Time (ms) to wait before starting tracing after program start.
+
 -a::
 --all-cpus::
Force system-wide collection.  Scripts run without a 
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 3ddd7568b456..64b68331048a 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -47,6 +47,7 @@ struct perf_ftrace {
int graph_noirqs;
int graph_verbose;
int graph_thresh;
+   unsigned intinitial_delay;
 };
 
 struct filter_entry {
@@ -594,13 +595,23 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
/* display column headers */
read_tracing_file_to_stdout("trace");
 
-   if (write_tracing_file("tracing_on", "1") < 0) {
-   pr_err("can't enable tracing\n");
-   goto out_close_fd;
+   if (!ftrace->initial_delay) {
+   if (write_tracing_file("tracing_on", "1") < 0) {
+   pr_err("can't enable tracing\n");
+   goto out_close_fd;
+   }
}
 
perf_evlist__start_workload(ftrace->evlist);
 
+   if (ftrace->initial_delay) {
+   usleep(ftrace->initial_delay * 1000);
+   if (write_tracing_file("tracing_on", "1") < 0) {
+   pr_err("can't enable tracing\n");
+   goto out_close_fd;
+   }
+   }
+
while (!done) {
if (poll(&pollfd, 1, -1) < 0)
break;
@@ -809,6 +820,8 @@ int cmd_ftrace(int argc, const char **argv)
 "size of per cpu buffer", parse_buffer_size),
OPT_BOOLEAN(0, "inherit", &ftrace.inherit,
"trace children processes"),
+   OPT_UINTEGER('D', "delay", &ftrace.initial_delay,
+"ms to wait before starting tracing after program start"),
OPT_END()
};
 
-- 
2.25.1



[PATCH v6 17/17] perf ftrace: add change log

2020-07-17 Thread Changbin Du
Add a change log after previous enhancements.

Signed-off-by: Changbin Du 
---
 tools/perf/builtin-ftrace.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index edf307f7d716..326fd03396d5 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -3,6 +3,7 @@
  * builtin-ftrace.c
  *
  * Copyright (c) 2013  LG Electronics,  Namhyung Kim 
+ * Copyright (c) 2020  Changbin Du , significant 
enhancement.
  */
 
 #include "builtin.h"
-- 
2.25.1



[PATCH v6 10/17] perf ftrace: add support for trace option funcgraph-irqs

2020-07-17 Thread Changbin Du
This adds an option '--graph-opts noirqs' to filter out functions executed
in irq context.

Signed-off-by: Changbin Du 

---
v2: option name '--nofuncgraph-irqs' -> '--graph-noirqs'.
---
 tools/perf/Documentation/perf-ftrace.txt |  1 +
 tools/perf/builtin-ftrace.c  | 21 -
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 2968a34239a4..21d3b444587a 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -101,6 +101,7 @@ OPTIONS
 --graph-opts::
List of options allowed to set:
  nosleep-time - Measure on-CPU time only for function_graph tracer.
+ noirqs   - Ignore functions that happen inside interrupt.
 
 SEE ALSO
 
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 835f810985f0..6402df3984c0 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -43,6 +43,7 @@ struct perf_ftrace {
boolinherit;
int func_stack_trace;
int graph_nosleep_time;
+   int graph_noirqs;
 };
 
 struct filter_entry {
@@ -205,6 +206,7 @@ static void reset_tracing_options(struct perf_ftrace 
*ftrace __maybe_unused)
write_tracing_option_file("function-fork", "0");
write_tracing_option_file("func_stack_trace", "0");
write_tracing_option_file("sleep-time", "1");
+   write_tracing_option_file("funcgraph-irqs", "1");
 }
 
 static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
@@ -397,6 +399,17 @@ static int set_tracing_sleep_time(struct perf_ftrace 
*ftrace)
return 0;
 }
 
+static int set_tracing_funcgraph_irqs(struct perf_ftrace *ftrace)
+{
+   if (!ftrace->graph_noirqs)
+   return 0;
+
+   if (write_tracing_option_file("funcgraph-irqs", "0") < 0)
+   return -1;
+
+   return 0;
+}
+
 static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
**argv)
 {
char *trace_file;
@@ -481,6 +494,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
goto out_reset;
}
 
+   if (set_tracing_funcgraph_irqs(ftrace) < 0) {
+   pr_err("failed to set tracing option funcgraph-irqs\n");
+   goto out_reset;
+   }
+
if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
goto out_reset;
@@ -661,6 +679,7 @@ static int parse_graph_tracer_opts(const struct option *opt,
struct perf_ftrace *ftrace = (struct perf_ftrace *) opt->value;
struct sublevel_option graph_tracer_opts[] = {
{ .name = "nosleep-time",   .value_ptr = 
&ftrace->graph_nosleep_time },
+   { .name = "noirqs", .value_ptr = 
&ftrace->graph_noirqs },
{ .name = NULL, }
};
 
@@ -715,7 +734,7 @@ int cmd_ftrace(int argc, const char **argv)
OPT_INTEGER('D', "graph-depth", &ftrace.graph_depth,
"Max depth for function graph tracer"),
OPT_CALLBACK(0, "graph-opts", &ftrace, "options",
-"graph tracer options, available options: nosleep-time",
+"graph tracer options, available options: 
nosleep-time,noirqs",
 parse_graph_tracer_opts),
OPT_CALLBACK('m', "buffer-size", &ftrace.percpu_buffer_size, "size",
 "size of per cpu buffer", parse_buffer_size),
-- 
2.25.1



[PATCH v6 09/17] perf ftrace: add support for trace option sleep-time

2020-07-17 Thread Changbin Du
This adds an option '--graph-opts nosleep-time' which allow us
only to measure on-CPU time. This option is function_graph tracer
only.

Signed-off-by: Changbin Du 

---
v3: switch to uniform option --graph-opts.
v2: option name '--nosleep-time' -> '--graph-nosleep-time'.
---
 tools/perf/Documentation/perf-ftrace.txt |  4 +++
 tools/perf/builtin-ftrace.c  | 41 
 2 files changed, 45 insertions(+)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 5a5069306141..2968a34239a4 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -98,6 +98,10 @@ OPTIONS
 --graph-depth=::
Set max depth for function graph tracer to follow
 
+--graph-opts::
+   List of options allowed to set:
+ nosleep-time - Measure on-CPU time only for function_graph tracer.
+
 SEE ALSO
 
 linkperf:perf-record[1], linkperf:perf-trace[1]
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index e7c8697294f0..835f810985f0 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -42,6 +42,7 @@ struct perf_ftrace {
unsigned long   percpu_buffer_size;
boolinherit;
int func_stack_trace;
+   int graph_nosleep_time;
 };
 
 struct filter_entry {
@@ -203,6 +204,7 @@ static void reset_tracing_options(struct perf_ftrace 
*ftrace __maybe_unused)
 {
write_tracing_option_file("function-fork", "0");
write_tracing_option_file("func_stack_trace", "0");
+   write_tracing_option_file("sleep-time", "1");
 }
 
 static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
@@ -384,6 +386,17 @@ static int set_tracing_trace_inherit(struct perf_ftrace 
*ftrace)
return 0;
 }
 
+static int set_tracing_sleep_time(struct perf_ftrace *ftrace)
+{
+   if (!ftrace->graph_nosleep_time)
+   return 0;
+
+   if (write_tracing_option_file("sleep-time", "0") < 0)
+   return -1;
+
+   return 0;
+}
+
 static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
**argv)
 {
char *trace_file;
@@ -463,6 +476,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
goto out_reset;
}
 
+   if (set_tracing_sleep_time(ftrace) < 0) {
+   pr_err("failed to set tracing option sleep-time\n");
+   goto out_reset;
+   }
+
if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
goto out_reset;
@@ -636,6 +654,26 @@ static int parse_func_tracer_opts(const struct option *opt,
return 0;
 }
 
+static int parse_graph_tracer_opts(const struct option *opt,
+ const char *str, int unset)
+{
+   int ret;
+   struct perf_ftrace *ftrace = (struct perf_ftrace *) opt->value;
+   struct sublevel_option graph_tracer_opts[] = {
+   { .name = "nosleep-time",   .value_ptr = 
&ftrace->graph_nosleep_time },
+   { .name = NULL, }
+   };
+
+   if (unset)
+   return 0;
+
+   ret = perf_parse_sublevel_options(str, graph_tracer_opts);
+   if (ret)
+   return ret;
+
+   return 0;
+}
+
 int cmd_ftrace(int argc, const char **argv)
 {
int ret;
@@ -676,6 +714,9 @@ int cmd_ftrace(int argc, const char **argv)
 "Set nograph filter on given functions", 
parse_filter_func),
OPT_INTEGER('D', "graph-depth", &ftrace.graph_depth,
"Max depth for function graph tracer"),
+   OPT_CALLBACK(0, "graph-opts", &ftrace, "options",
+"graph tracer options, available options: nosleep-time",
+parse_graph_tracer_opts),
OPT_CALLBACK('m', "buffer-size", &ftrace.percpu_buffer_size, "size",
 "size of per cpu buffer", parse_buffer_size),
OPT_BOOLEAN(0, "inherit", &ftrace.inherit,
-- 
2.25.1



[PATCH v6 06/17] perf ftrace: add option '--inherit' to trace children processes

2020-07-17 Thread Changbin Du
This adds an option '--inherit' to allow us trace children
processes spawned by our target.

Signed-off-by: Changbin Du 

---
v2: option name '--trace-children' -> '--inherit'.
---
 tools/perf/Documentation/perf-ftrace.txt |  3 ++
 tools/perf/builtin-ftrace.c  | 38 
 2 files changed, 41 insertions(+)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index dcac0d75a0e5..3eee073a7042 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -57,6 +57,9 @@ OPTIONS
Set the size of per-cpu tracing buffer,  is expected to
be a number with appended unit character - B/K/M/G.
 
+--inherit::
+   Trace children processes spawned by our target.
+
 -T::
 --trace-funcs=::
Only trace functions given by the argument.  Multiple functions
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 6ce626a2d0d1..765ebd56e05f 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -39,6 +39,7 @@ struct perf_ftrace {
struct list_headnograph_funcs;
int graph_depth;
unsigned long   percpu_buffer_size;
+   boolinherit;
 };
 
 struct filter_entry {
@@ -180,9 +181,27 @@ static int write_tracing_file_int(const char *name, int 
value)
return 0;
 }
 
+static int write_tracing_option_file(const char *name, const char *val)
+{
+   char *file;
+   int ret;
+
+   if (asprintf(&file, "options/%s", name) < 0)
+   return -1;
+
+   ret = __write_tracing_file(file, val, false);
+   free(file);
+   return ret;
+}
+
 static int reset_tracing_cpu(void);
 static void reset_tracing_filters(void);
 
+static void reset_tracing_options(struct perf_ftrace *ftrace __maybe_unused)
+{
+   write_tracing_option_file("function-fork", "0");
+}
+
 static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
 {
if (write_tracing_file("tracing_on", "0") < 0)
@@ -201,6 +220,7 @@ static int reset_tracing_files(struct perf_ftrace *ftrace 
__maybe_unused)
return -1;
 
reset_tracing_filters();
+   reset_tracing_options(ftrace);
return 0;
 }
 
@@ -339,6 +359,17 @@ static int set_tracing_percpu_buffer_size(struct 
perf_ftrace *ftrace)
return 0;
 }
 
+static int set_tracing_trace_inherit(struct perf_ftrace *ftrace)
+{
+   if (!ftrace->inherit)
+   return 0;
+
+   if (write_tracing_option_file("function-fork", "1") < 0)
+   return -1;
+
+   return 0;
+}
+
 static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
**argv)
 {
char *trace_file;
@@ -408,6 +439,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
goto out_reset;
}
 
+   if (set_tracing_trace_inherit(ftrace) < 0) {
+   pr_err("failed to set tracing option function-fork\n");
+   goto out_reset;
+   }
+
if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
goto out_reset;
@@ -600,6 +636,8 @@ int cmd_ftrace(int argc, const char **argv)
"Max depth for function graph tracer"),
OPT_CALLBACK('m', "buffer-size", &ftrace.percpu_buffer_size, "size",
 "size of per cpu buffer", parse_buffer_size),
+   OPT_BOOLEAN(0, "inherit", &ftrace.inherit,
+   "trace children processes"),
OPT_END()
};
 
-- 
2.25.1



[PATCH v6 11/17] perf ftrace: add support for tracing option 'irq-info'

2020-07-17 Thread Changbin Du
This adds support to display irq context info for function tracer. To do
this, just specify a '--func-opts irq-info' option.

Signed-off-by: Changbin Du 
---
 tools/perf/Documentation/perf-ftrace.txt |  1 +
 tools/perf/builtin-ftrace.c  | 21 -
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 21d3b444587a..3ab1fe040994 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -77,6 +77,7 @@ OPTIONS
 --func-opts::
List of options allowed to set:
  call-graph - Display kernel stack trace for function tracer.
+ irq-info   - Display irq context info for function tracer.
 
 -G::
 --graph-funcs=::
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 6402df3984c0..95d87c5966ad 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -42,6 +42,7 @@ struct perf_ftrace {
unsigned long   percpu_buffer_size;
boolinherit;
int func_stack_trace;
+   int func_irq_info;
int graph_nosleep_time;
int graph_noirqs;
 };
@@ -207,6 +208,7 @@ static void reset_tracing_options(struct perf_ftrace 
*ftrace __maybe_unused)
write_tracing_option_file("func_stack_trace", "0");
write_tracing_option_file("sleep-time", "1");
write_tracing_option_file("funcgraph-irqs", "1");
+   write_tracing_option_file("irq-info", "0");
 }
 
 static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
@@ -294,6 +296,17 @@ static int set_tracing_func_stack_trace(struct perf_ftrace 
*ftrace)
return 0;
 }
 
+static int set_tracing_func_irqinfo(struct perf_ftrace *ftrace)
+{
+   if (!ftrace->func_irq_info)
+   return 0;
+
+   if (write_tracing_option_file("irq-info", "1") < 0)
+   return -1;
+
+   return 0;
+}
+
 static int reset_tracing_cpu(void)
 {
struct perf_cpu_map *cpumap = perf_cpu_map__new(NULL);
@@ -469,6 +482,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
goto out_reset;
}
 
+   if (set_tracing_func_irqinfo(ftrace) < 0) {
+   pr_err("failed to set tracing option irq-info\n");
+   goto out_reset;
+   }
+
if (set_tracing_filters(ftrace) < 0) {
pr_err("failed to set tracing filters\n");
goto out_reset;
@@ -659,6 +677,7 @@ static int parse_func_tracer_opts(const struct option *opt,
struct perf_ftrace *ftrace = (struct perf_ftrace *) opt->value;
struct sublevel_option func_tracer_opts[] = {
{ .name = "call-graph", .value_ptr = &ftrace->func_stack_trace 
},
+   { .name = "irq-info",   .value_ptr = &ftrace->func_irq_info },
{ .name = NULL, }
};
 
@@ -724,7 +743,7 @@ int cmd_ftrace(int argc, const char **argv)
OPT_CALLBACK('N', "notrace-funcs", &ftrace.notrace, "func",
 "do not trace given functions", parse_filter_func),
OPT_CALLBACK(0, "func-opts", &ftrace, "options",
-"function tracer options, available options: call-graph",
+"function tracer options, available options: 
call-graph,irq-info",
 parse_func_tracer_opts),
OPT_CALLBACK('G', "graph-funcs", &ftrace.graph_funcs, "func",
 "trace given functions using function_graph tracer",
-- 
2.25.1



[PATCH v6 05/17] perf ftrace: show trace column header

2020-07-17 Thread Changbin Du
This makes perf-ftrace display column header before printing trace.

  $ sudo perf ftrace
  # tracer: function
  #
  # entries-in-buffer/entries-written: 0/0   #P:8
  #
  #TASK-PID CPU#   TIMESTAMP  FUNCTION
  #  | | |   | |
 <...>-9246  [006]  10726.262760: mutex_unlock <-rb_simple_write
 <...>-9246  [006]  10726.262764: __fsnotify_parent <-vfs_write
 <...>-9246  [006]  10726.262765: fsnotify <-vfs_write
 <...>-9246  [006]  10726.262766: __sb_end_write <-vfs_write
 <...>-9246  [006]  10726.262767: fpregs_assert_state_consistent 
<-do_syscall_64

Signed-off-by: Changbin Du 
---
 tools/perf/builtin-ftrace.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 3ea3aaa4650b..6ce626a2d0d1 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -433,6 +433,9 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
fcntl(trace_fd, F_SETFL, O_NONBLOCK);
pollfd.fd = trace_fd;
 
+   /* display column headers */
+   read_tracing_file_to_stdout("trace");
+
if (write_tracing_file("tracing_on", "1") < 0) {
pr_err("can't enable tracing\n");
goto out_close_fd;
-- 
2.25.1



[PATCH v6 07/17] perf: util: add general function to parse sublevel options

2020-07-17 Thread Changbin Du
This factors out a general function perf_parse_sublevel_options() to parse
sublevel options. The 'sublevel' options is something like the '--debug'
options which allow more sublevel options.

Signed-off-by: Changbin Du 

---
v2: add util/parse-sublevel-options.c
---
 tools/perf/util/Build|  1 +
 tools/perf/util/debug.c  | 61 ++---
 tools/perf/util/parse-sublevel-options.c | 70 
 tools/perf/util/parse-sublevel-options.h | 11 
 4 files changed, 99 insertions(+), 44 deletions(-)
 create mode 100644 tools/perf/util/parse-sublevel-options.c
 create mode 100644 tools/perf/util/parse-sublevel-options.h

diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 8d18380ecd10..e86607ada0b5 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -117,6 +117,7 @@ endif
 perf-y += parse-branch-options.o
 perf-y += dump-insn.o
 perf-y += parse-regs-options.o
+perf-y += parse-sublevel-options.o
 perf-y += term.o
 perf-y += help-unknown-cmd.o
 perf-y += mem-events.o
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index adb656745ecc..5cda5565777a 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -20,6 +20,7 @@
 #include "target.h"
 #include "ui/helpline.h"
 #include "ui/ui.h"
+#include "util/parse-sublevel-options.h"
 
 #include 
 
@@ -173,65 +174,37 @@ void trace_event(union perf_event *event)
 trace_event_printer, event);
 }
 
-static struct debug_variable {
-   const char *name;
-   int *ptr;
-} debug_variables[] = {
-   { .name = "verbose",.ptr = &verbose },
-   { .name = "ordered-events", .ptr = &debug_ordered_events},
-   { .name = "stderr", .ptr = &redirect_to_stderr},
-   { .name = "data-convert",   .ptr = &debug_data_convert },
-   { .name = "perf-event-open",.ptr = &debug_peo_args },
+static struct sublevel_option debug_opts[] = {
+   { .name = "verbose",.value_ptr = &verbose },
+   { .name = "ordered-events", .value_ptr = &debug_ordered_events},
+   { .name = "stderr", .value_ptr = &redirect_to_stderr},
+   { .name = "data-convert",   .value_ptr = &debug_data_convert },
+   { .name = "perf-event-open",.value_ptr = &debug_peo_args },
{ .name = NULL, }
 };
 
 int perf_debug_option(const char *str)
 {
-   struct debug_variable *var = &debug_variables[0];
-   char *vstr, *s = strdup(str);
-   int v = 1;
-
-   vstr = strchr(s, '=');
-   if (vstr)
-   *vstr++ = 0;
-
-   while (var->name) {
-   if (!strcmp(s, var->name))
-   break;
-   var++;
-   }
-
-   if (!var->name) {
-   pr_err("Unknown debug variable name '%s'\n", s);
-   free(s);
-   return -1;
-   }
+   int ret;
 
-   if (vstr) {
-   v = atoi(vstr);
-   /*
-* Allow only values in range (0, 10),
-* otherwise set 0.
-*/
-   v = (v < 0) || (v > 10) ? 0 : v;
-   }
+   ret = perf_parse_sublevel_options(str, debug_opts);
+   if (ret)
+   return ret;
 
-   if (quiet)
-   v = -1;
+   /* Allow only verbose value in range (0, 10), otherwise set 0. */
+   verbose = (verbose < 0) || (verbose > 10) ? 0 : verbose;
 
-   *var->ptr = v;
-   free(s);
return 0;
 }
 
 int perf_quiet_option(void)
 {
-   struct debug_variable *var = &debug_variables[0];
+   struct sublevel_option *opt = &debug_opts[0];
 
/* disable all debug messages */
-   while (var->name) {
-   *var->ptr = -1;
-   var++;
+   while (opt->name) {
+   *opt->value_ptr = -1;
+   opt++;
}
 
return 0;
diff --git a/tools/perf/util/parse-sublevel-options.c 
b/tools/perf/util/parse-sublevel-options.c
new file mode 100644
index ..a841d17ffd57
--- /dev/null
+++ b/tools/perf/util/parse-sublevel-options.c
@@ -0,0 +1,70 @@
+#include 
+#include 
+#include 
+#include 
+
+#include "util/debug.h"
+#include "util/parse-sublevel-options.h"
+
+static int parse_one_sublevel_option(const char *str,
+struct sublevel_option *opts)
+{
+   struct sublevel_option *opt = opts;
+   char *vstr, *s = strdup(str);
+   int v = 1;
+
+   if (!s) {
+   pr_err("no memory\n");
+   return -1;
+   }
+
+   vstr = strchr(s, '=');
+   if (vstr)
+   *vstr++ = 0;
+
+   while (opt->name) {

[PATCH v6 08/17] perf ftrace: add support for tracing option 'func_stack_trace'

2020-07-17 Thread Changbin Du
This adds support to display call trace for function tracer. To do this,
just specify a '--func-opts call-graph' option.

$ sudo perf ftrace -T vfs_read --func-opts call-graph
 iio-sensor-prox-855   [003]   6168.369657: vfs_read <-ksys_read
 iio-sensor-prox-855   [003]   6168.369677: 
 => vfs_read
 => ksys_read
 => __x64_sys_read
 => do_syscall_64
 => entry_SYSCALL_64_after_hwframe
 ...

Signed-off-by: Changbin Du 

---
v3: switch to uniform option --func-opts.
v2: option name '-s' -> '--func-call-graph'
---
 tools/perf/Documentation/perf-ftrace.txt |  4 +++
 tools/perf/builtin-ftrace.c  | 42 
 2 files changed, 46 insertions(+)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 3eee073a7042..5a5069306141 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -74,6 +74,10 @@ OPTIONS
(or glob patterns).  It will be passed to 'set_ftrace_notrace'
in tracefs.
 
+--func-opts::
+   List of options allowed to set:
+ call-graph - Display kernel stack trace for function tracer.
+
 -G::
 --graph-funcs=::
Set graph filter on the given function (or a glob pattern).
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 765ebd56e05f..e7c8697294f0 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -27,6 +27,7 @@
 #include "util/cap.h"
 #include "util/config.h"
 #include "util/units.h"
+#include "util/parse-sublevel-options.h"
 
 struct perf_ftrace {
struct evlist   *evlist;
@@ -40,6 +41,7 @@ struct perf_ftrace {
int graph_depth;
unsigned long   percpu_buffer_size;
boolinherit;
+   int func_stack_trace;
 };
 
 struct filter_entry {
@@ -200,6 +202,7 @@ static void reset_tracing_filters(void);
 static void reset_tracing_options(struct perf_ftrace *ftrace __maybe_unused)
 {
write_tracing_option_file("function-fork", "0");
+   write_tracing_option_file("func_stack_trace", "0");
 }
 
 static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
@@ -276,6 +279,17 @@ static int set_tracing_cpu(struct perf_ftrace *ftrace)
return set_tracing_cpumask(cpumap);
 }
 
+static int set_tracing_func_stack_trace(struct perf_ftrace *ftrace)
+{
+   if (!ftrace->func_stack_trace)
+   return 0;
+
+   if (write_tracing_option_file("func_stack_trace", "1") < 0)
+   return -1;
+
+   return 0;
+}
+
 static int reset_tracing_cpu(void)
 {
struct perf_cpu_map *cpumap = perf_cpu_map__new(NULL);
@@ -424,6 +438,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
goto out_reset;
}
 
+   if (set_tracing_func_stack_trace(ftrace) < 0) {
+   pr_err("failed to set tracing option func_stack_trace\n");
+   goto out_reset;
+   }
+
if (set_tracing_filters(ftrace) < 0) {
pr_err("failed to set tracing filters\n");
goto out_reset;
@@ -597,6 +616,26 @@ static int parse_buffer_size(const struct option *opt,
return -1;
 }
 
+static int parse_func_tracer_opts(const struct option *opt,
+ const char *str, int unset)
+{
+   int ret;
+   struct perf_ftrace *ftrace = (struct perf_ftrace *) opt->value;
+   struct sublevel_option func_tracer_opts[] = {
+   { .name = "call-graph", .value_ptr = &ftrace->func_stack_trace 
},
+   { .name = NULL, }
+   };
+
+   if (unset)
+   return 0;
+
+   ret = perf_parse_sublevel_options(str, func_tracer_opts);
+   if (ret)
+   return ret;
+
+   return 0;
+}
+
 int cmd_ftrace(int argc, const char **argv)
 {
int ret;
@@ -627,6 +666,9 @@ int cmd_ftrace(int argc, const char **argv)
 parse_filter_func),
OPT_CALLBACK('N', "notrace-funcs", &ftrace.notrace, "func",
 "do not trace given functions", parse_filter_func),
+   OPT_CALLBACK(0, "func-opts", &ftrace, "options",
+"function tracer options, available options: call-graph",
+parse_func_tracer_opts),
OPT_CALLBACK('G', "graph-funcs", &ftrace.graph_funcs, "func",
 "trace given functions using function_graph tracer",
 parse_filter_func),
-- 
2.25.1



[PATCH v6 03/17] perf ftrace: factor out function write_tracing_file_int()

2020-07-17 Thread Changbin Du
We will reuse this function later.

Signed-off-by: Changbin Du 
---
 tools/perf/builtin-ftrace.c | 17 -
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 3c0e60fdfe0f..9abf97c29cb6 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -168,6 +168,17 @@ static int read_tracing_file_to_stdout(const char *name)
return ret;
 }
 
+static int write_tracing_file_int(const char *name, int value)
+{
+   char buf[16];
+
+   snprintf(buf, sizeof(buf), "%d", value);
+   if (write_tracing_file(name, buf) < 0)
+   return -1;
+
+   return 0;
+}
+
 static int reset_tracing_cpu(void);
 static void reset_tracing_filters(void);
 
@@ -298,8 +309,6 @@ static void reset_tracing_filters(void)
 
 static int set_tracing_depth(struct perf_ftrace *ftrace)
 {
-   char buf[16];
-
if (ftrace->graph_depth == 0)
return 0;
 
@@ -308,9 +317,7 @@ static int set_tracing_depth(struct perf_ftrace *ftrace)
return -1;
}
 
-   snprintf(buf, sizeof(buf), "%d", ftrace->graph_depth);
-
-   if (write_tracing_file("max_graph_depth", buf) < 0)
+   if (write_tracing_file_int("max_graph_depth", ftrace->graph_depth) < 0)
return -1;
 
return 0;
-- 
2.25.1



[PATCH v6 04/17] perf ftrace: add option '-m/--buffer-size' to set per-cpu buffer size

2020-07-17 Thread Changbin Du
This adds an option '-m/--buffer-size' to allow us set the size of per-cpu
tracing buffer.

Signed-off-by: Changbin Du 

---
v2: support units as a suffix.
---
 tools/perf/Documentation/perf-ftrace.txt |  5 +++
 tools/perf/builtin-ftrace.c  | 56 +++-
 2 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index d79560dea19f..dcac0d75a0e5 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -52,6 +52,11 @@ OPTIONS
Ranges of CPUs are specified with -: 0-2.
Default is to trace on all online CPUs.
 
+-m::
+--buffer-size::
+   Set the size of per-cpu tracing buffer,  is expected to
+   be a number with appended unit character - B/K/M/G.
+
 -T::
 --trace-funcs=::
Only trace functions given by the argument.  Multiple functions
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 9abf97c29cb6..3ea3aaa4650b 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -26,7 +26,7 @@
 #include "thread_map.h"
 #include "util/cap.h"
 #include "util/config.h"
-
+#include "util/units.h"
 
 struct perf_ftrace {
struct evlist   *evlist;
@@ -38,6 +38,7 @@ struct perf_ftrace {
struct list_headgraph_funcs;
struct list_headnograph_funcs;
int graph_depth;
+   unsigned long   percpu_buffer_size;
 };
 
 struct filter_entry {
@@ -323,6 +324,21 @@ static int set_tracing_depth(struct perf_ftrace *ftrace)
return 0;
 }
 
+static int set_tracing_percpu_buffer_size(struct perf_ftrace *ftrace)
+{
+   int ret;
+
+   if (ftrace->percpu_buffer_size == 0)
+   return 0;
+
+   ret = write_tracing_file_int("buffer_size_kb",
+ftrace->percpu_buffer_size / 1024);
+   if (ret < 0)
+   return ret;
+
+   return 0;
+}
+
 static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
**argv)
 {
char *trace_file;
@@ -387,6 +403,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
goto out_reset;
}
 
+   if (set_tracing_percpu_buffer_size(ftrace) < 0) {
+   pr_err("failed to set tracing per-cpu buffer size\n");
+   goto out_reset;
+   }
+
if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
goto out_reset;
@@ -506,6 +527,37 @@ static void delete_filter_func(struct list_head *head)
}
 }
 
+static int parse_buffer_size(const struct option *opt,
+const char *str, int unset)
+{
+   unsigned long *s = (unsigned long *)opt->value;
+   static struct parse_tag tags_size[] = {
+   { .tag  = 'B', .mult = 1   },
+   { .tag  = 'K', .mult = 1 << 10 },
+   { .tag  = 'M', .mult = 1 << 20 },
+   { .tag  = 'G', .mult = 1 << 30 },
+   { .tag  = 0 },
+   };
+   unsigned long val;
+
+   if (unset) {
+   *s = 0;
+   return 0;
+   }
+
+   val = parse_tag_value(str, tags_size);
+   if (val != (unsigned long) -1) {
+   if (val < 1024) {
+   pr_err("buffer size too small, must larger than 1KB.");
+   return -1;
+   }
+   *s = val;
+   return 0;
+   }
+
+   return -1;
+}
+
 int cmd_ftrace(int argc, const char **argv)
 {
int ret;
@@ -543,6 +595,8 @@ int cmd_ftrace(int argc, const char **argv)
 "Set nograph filter on given functions", 
parse_filter_func),
OPT_INTEGER('D', "graph-depth", &ftrace.graph_depth,
"Max depth for function graph tracer"),
+   OPT_CALLBACK('m', "buffer-size", &ftrace.percpu_buffer_size, "size",
+"size of per cpu buffer", parse_buffer_size),
OPT_END()
};
 
-- 
2.25.1



[PATCH v6 00/17] perf: ftrace enhancement

2020-07-17 Thread Changbin Du
The perf has basic kernel ftrace support but lack support of most tracing
options. This serias is target to enhance the perf ftrace functionality so
that we can make full use of kernel ftrace with perf.

In general, this serias be cataloged into two main changes:
  1) Improve usability of existing functions. For example, we don't need to type
 extra option to select the tracer.
  2) Add new options to support all other ftrace functions.

Here is a glance of all ftrace functions with this serias:

$ sudo perf ftrace -h

 Usage: perf ftrace [] []
or: perf ftrace [] --  []

-a, --all-cpussystem-wide collection from all CPUs
-C, --cpulist of cpus to monitor
-D, --delayms to wait before starting tracing after program start
-F, --funcs   Show available functions to filter
-G, --graph-funcs 
  trace given functions using function_graph tracer
-g, --nograph-funcs 
  Set nograph filter on given functions
-m, --buffer-size 
  size of per cpu buffer
-N, --notrace-funcs 
  do not trace given functions
-p, --pidtrace on existing process id
-T, --trace-funcs 
  trace given functions using function tracer
-t, --tracer 
  tracer to use: function or function_graph (This 
option is deprecated)
-v, --verbose be more verbose
--func-opts 
  function tracer options, available options: 
call-graph,irq-info
--graph-opts 
  graph tracer options, available options: 
nosleep-time,noirqs,verbose,thresh=,depth=
--inherit trace children processes

v6:
  o fix return value of read_tracing_file_to_stdout().
  o make __cmd_ftrace() shorter.
  o remove option '-t, --tid '.
v5:
  o trivial fixes.
v4:
  o add util/parse-sublevel-options.c
  O remove -D/--graph-depth
v3:
  o add --func-opts and --graph-opts to set tracer specific options.
  o support units as a suffix for option '-m/--buffer-size'.
v2:
  o patches for option '-u/--userstacktrace' and '--no-pager' are dropped.
  o update all related perf documentation.
  o rename some options. Now all funcgraph tracer options are prefixed with
'--graph-', while all function tracer options are prefixed with '--func-'.
  o mark old options deprecated instead of removing them.


Changbin Du (17):
  perf ftrace: select function/function_graph tracer automatically
  perf ftrace: add option '-F/--funcs' to list available functions
  perf ftrace: factor out function write_tracing_file_int()
  perf ftrace: add option '-m/--buffer-size' to set per-cpu buffer size
  perf ftrace: show trace column header
  perf ftrace: add option '--inherit' to trace children processes
  perf: util: add general function to parse sublevel options
  perf ftrace: add support for tracing option 'func_stack_trace'
  perf ftrace: add support for trace option sleep-time
  perf ftrace: add support for trace option funcgraph-irqs
  perf ftrace: add support for tracing option 'irq-info'
  perf ftrace: add option 'verbose' to show more info for graph tracer
  perf ftrace: add support for trace option tracing_thresh
  perf: ftrace: allow set graph depth by '--graph-opts'
  perf ftrace: add option -D/--delay to delay tracing
  perf: ftrace: Add set_tracing_options() to set all trace options
  perf ftrace: add change log

 tools/perf/Documentation/perf-config.txt |   5 -
 tools/perf/Documentation/perf-ftrace.txt |  33 +-
 tools/perf/builtin-ftrace.c  | 412 +--
 tools/perf/util/Build|   1 +
 tools/perf/util/debug.c  |  61 +---
 tools/perf/util/parse-sublevel-options.c |  70 
 tools/perf/util/parse-sublevel-options.h |  11 +
 7 files changed, 507 insertions(+), 86 deletions(-)
 create mode 100644 tools/perf/util/parse-sublevel-options.c
 create mode 100644 tools/perf/util/parse-sublevel-options.h

-- 
2.25.1



[PATCH v6 02/17] perf ftrace: add option '-F/--funcs' to list available functions

2020-07-17 Thread Changbin Du
This adds an option '-F/--funcs' to list all available functions to trace,
which is read from tracing file 'available_filter_functions'.

$ sudo ./perf ftrace -F | head
trace_initcall_finish_cb
initcall_blacklisted
do_one_initcall
do_one_initcall
trace_initcall_start_cb
run_init_process
try_to_run_init_process
match_dev_by_label
match_dev_by_uuid
rootfs_init_fs_context

Signed-off-by: Changbin Du 

---
v3: fix return value issue.
v2: option name '-l/--list-functions' -> '-F/--funcs'
---
 tools/perf/Documentation/perf-ftrace.txt |  4 +++
 tools/perf/builtin-ftrace.c  | 46 
 2 files changed, 50 insertions(+)

diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index 952e46669168..d79560dea19f 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -30,6 +30,10 @@ OPTIONS
 --verbose=::
 Verbosity level.
 
+-F::
+--funcs::
+List all available functions to trace.
+
 -p::
 --pid=::
Trace on existing process id (comma separated list).
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 5f53da87040d..3c0e60fdfe0f 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -32,6 +32,7 @@ struct perf_ftrace {
struct evlist   *evlist;
struct target   target;
const char  *tracer;
+   boollist_avail_functions;
struct list_headfilters;
struct list_headnotrace;
struct list_headgraph_funcs;
@@ -127,6 +128,46 @@ static int append_tracing_file(const char *name, const 
char *val)
return __write_tracing_file(name, val, true);
 }
 
+static int read_tracing_file_to_stdout(const char *name)
+{
+   char buf[4096];
+   char *file;
+   int fd;
+   int ret = -1;
+
+   file = get_tracing_file(name);
+   if (!file) {
+   pr_debug("cannot get tracing file: %s\n", name);
+   return -1;
+   }
+
+   fd = open(file, O_RDONLY);
+   if (fd < 0) {
+   pr_debug("cannot open tracing file: %s: %s\n",
+name, str_error_r(errno, buf, sizeof(buf)));
+   goto out;
+   }
+
+   /* read contents to stdout */
+   while (true) {
+   int n = read(fd, buf, sizeof(buf));
+   if (n == 0)
+   break;
+   else if (n < 0)
+   goto out_close;
+
+   if (fwrite(buf, n, 1, stdout) != 1)
+   goto out_close;
+   }
+   ret = 0;
+
+out_close:
+   close(fd);
+out:
+   put_tracing_file(file);
+   return ret;
+}
+
 static int reset_tracing_cpu(void);
 static void reset_tracing_filters(void);
 
@@ -301,6 +342,9 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
argc, const char **argv)
signal(SIGCHLD, sig_handler);
signal(SIGPIPE, sig_handler);
 
+   if (ftrace->list_avail_functions)
+   return 
read_tracing_file_to_stdout("available_filter_functions");
+
if (reset_tracing_files(ftrace) < 0) {
pr_err("failed to reset ftrace\n");
goto out;
@@ -470,6 +514,8 @@ int cmd_ftrace(int argc, const char **argv)
const struct option ftrace_options[] = {
OPT_STRING('t', "tracer", &ftrace.tracer, "tracer",
   "tracer to use: function or function_graph (This option is 
deprecated)"),
+   OPT_BOOLEAN('F', "funcs", &ftrace.list_avail_functions,
+   "Show available functions to filter"),
OPT_STRING('p', "pid", &ftrace.target.pid, "pid",
   "trace on existing process id"),
OPT_INCR('v', "verbose", &verbose,
-- 
2.25.1



[PATCH v6 01/17] perf ftrace: select function/function_graph tracer automatically

2020-07-17 Thread Changbin Du
The '-g/-G' options have already implied function_graph tracer should be
used instead of function tracer. So the extra option '--tracer' can be
killed.

This patch changes the behavior as below:
  - By default, function tracer is used.
  - If '-g' or '-G' option is on, then function_graph tracer is used.
  - The perf configuration item 'ftrace.tracer' is marked as deprecated.
  - The option '--tracer' is marked as deprecated.

Here are some examples.

This will start tracing all functions using function tracer:
  $ sudo perf ftrace

This will trace all functions using function graph tracer:
  $ sudo perf ftrace -G '*'

This will trace function vfs_read using function graph tracer:
  $ sudo perf ftrace -G vfs_read

Signed-off-by: Changbin Du 

---
v3: remove default '*' for -G/-T.
---
 tools/perf/Documentation/perf-config.txt |  5 -
 tools/perf/Documentation/perf-ftrace.txt |  2 +-
 tools/perf/builtin-ftrace.c  | 15 ++-
 3 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/tools/perf/Documentation/perf-config.txt 
b/tools/perf/Documentation/perf-config.txt
index c7d3df5798e2..a25fee7de3b2 100644
--- a/tools/perf/Documentation/perf-config.txt
+++ b/tools/perf/Documentation/perf-config.txt
@@ -612,11 +612,6 @@ trace.*::
"libbeauty", the default, to use the same argument beautifiers 
used in the
strace-like sys_enter+sys_exit lines.
 
-ftrace.*::
-   ftrace.tracer::
-   Can be used to select the default tracer. Possible values are
-   'function' and 'function_graph'.
-
 llvm.*::
llvm.clang-path::
Path to clang. If omit, search it from $PATH.
diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index b80c84307dc9..952e46669168 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -24,7 +24,7 @@ OPTIONS
 
 -t::
 --tracer=::
-   Tracer to use: function_graph or function.
+   Tracer to use: function_graph or function. This option is deprecated.
 
 -v::
 --verbose=::
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 2bfc1b0db536..5f53da87040d 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -27,7 +27,6 @@
 #include "util/cap.h"
 #include "util/config.h"
 
-#define DEFAULT_TRACER  "function_graph"
 
 struct perf_ftrace {
struct evlist   *evlist;
@@ -419,6 +418,7 @@ static int perf_ftrace_config(const char *var, const char 
*value, void *cb)
if (strcmp(var, "ftrace.tracer"))
return -1;
 
+   pr_warning("Configuration ftrace.tracer is deprecated\n");
if (!strcmp(value, "function_graph") ||
!strcmp(value, "function")) {
ftrace->tracer = value;
@@ -459,7 +459,7 @@ int cmd_ftrace(int argc, const char **argv)
 {
int ret;
struct perf_ftrace ftrace = {
-   .tracer = DEFAULT_TRACER,
+   .tracer = "function",
.target = { .uid = UINT_MAX, },
};
const char * const ftrace_usage[] = {
@@ -469,7 +469,7 @@ int cmd_ftrace(int argc, const char **argv)
};
const struct option ftrace_options[] = {
OPT_STRING('t', "tracer", &ftrace.tracer, "tracer",
-  "tracer to use: function_graph(default) or function"),
+  "tracer to use: function or function_graph (This option is 
deprecated)"),
OPT_STRING('p', "pid", &ftrace.target.pid, "pid",
   "trace on existing process id"),
OPT_INCR('v', "verbose", &verbose,
@@ -479,11 +479,13 @@ int cmd_ftrace(int argc, const char **argv)
OPT_STRING('C', "cpu", &ftrace.target.cpu_list, "cpu",
"list of cpus to monitor"),
OPT_CALLBACK('T', "trace-funcs", &ftrace.filters, "func",
-"trace given functions only", parse_filter_func),
+"trace given functions using function tracer",
+parse_filter_func),
OPT_CALLBACK('N', "notrace-funcs", &ftrace.notrace, "func",
 "do not trace given functions", parse_filter_func),
OPT_CALLBACK('G', "graph-funcs", &ftrace.graph_funcs, "func",
-"Set graph filter on given functions", parse_filter_func),
+"trace given functions using function_graph tracer",
+parse_filter_func),
  

[PATCH v6 01/17] perf ftrace: select function/function_graph tracer automatically

2020-07-17 Thread Changbin Du
The '-g/-G' options have already implied function_graph tracer should be
used instead of function tracer. So the extra option '--tracer' can be
killed.

This patch changes the behavior as below:
  - By default, function tracer is used.
  - If '-g' or '-G' option is on, then function_graph tracer is used.
  - The perf configuration item 'ftrace.tracer' is marked as deprecated.
  - The option '--tracer' is marked as deprecated.

Here are some examples.

This will start tracing all functions using function tracer:
  $ sudo perf ftrace

This will trace all functions using function graph tracer:
  $ sudo perf ftrace -G '*'

This will trace function vfs_read using function graph tracer:
  $ sudo perf ftrace -G vfs_read

Signed-off-by: Changbin Du 

---
v3: remove default '*' for -G/-T.
---
 tools/perf/Documentation/perf-config.txt |  5 -
 tools/perf/Documentation/perf-ftrace.txt |  2 +-
 tools/perf/builtin-ftrace.c  | 15 ++-
 3 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/tools/perf/Documentation/perf-config.txt 
b/tools/perf/Documentation/perf-config.txt
index c7d3df5798e2..a25fee7de3b2 100644
--- a/tools/perf/Documentation/perf-config.txt
+++ b/tools/perf/Documentation/perf-config.txt
@@ -612,11 +612,6 @@ trace.*::
"libbeauty", the default, to use the same argument beautifiers 
used in the
strace-like sys_enter+sys_exit lines.
 
-ftrace.*::
-   ftrace.tracer::
-   Can be used to select the default tracer. Possible values are
-   'function' and 'function_graph'.
-
 llvm.*::
llvm.clang-path::
Path to clang. If omit, search it from $PATH.
diff --git a/tools/perf/Documentation/perf-ftrace.txt 
b/tools/perf/Documentation/perf-ftrace.txt
index b80c84307dc9..952e46669168 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -24,7 +24,7 @@ OPTIONS
 
 -t::
 --tracer=::
-   Tracer to use: function_graph or function.
+   Tracer to use: function_graph or function. This option is deprecated.
 
 -v::
 --verbose=::
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 2bfc1b0db536..5f53da87040d 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -27,7 +27,6 @@
 #include "util/cap.h"
 #include "util/config.h"
 
-#define DEFAULT_TRACER  "function_graph"
 
 struct perf_ftrace {
struct evlist   *evlist;
@@ -419,6 +418,7 @@ static int perf_ftrace_config(const char *var, const char 
*value, void *cb)
if (strcmp(var, "ftrace.tracer"))
return -1;
 
+   pr_warning("Configuration ftrace.tracer is deprecated\n");
if (!strcmp(value, "function_graph") ||
!strcmp(value, "function")) {
ftrace->tracer = value;
@@ -459,7 +459,7 @@ int cmd_ftrace(int argc, const char **argv)
 {
int ret;
struct perf_ftrace ftrace = {
-   .tracer = DEFAULT_TRACER,
+   .tracer = "function",
.target = { .uid = UINT_MAX, },
};
const char * const ftrace_usage[] = {
@@ -469,7 +469,7 @@ int cmd_ftrace(int argc, const char **argv)
};
const struct option ftrace_options[] = {
OPT_STRING('t', "tracer", &ftrace.tracer, "tracer",
-  "tracer to use: function_graph(default) or function"),
+  "tracer to use: function or function_graph (This option is 
deprecated)"),
OPT_STRING('p', "pid", &ftrace.target.pid, "pid",
   "trace on existing process id"),
OPT_INCR('v', "verbose", &verbose,
@@ -479,11 +479,13 @@ int cmd_ftrace(int argc, const char **argv)
OPT_STRING('C', "cpu", &ftrace.target.cpu_list, "cpu",
"list of cpus to monitor"),
OPT_CALLBACK('T', "trace-funcs", &ftrace.filters, "func",
-"trace given functions only", parse_filter_func),
+"trace given functions using function tracer",
+parse_filter_func),
OPT_CALLBACK('N', "notrace-funcs", &ftrace.notrace, "func",
 "do not trace given functions", parse_filter_func),
OPT_CALLBACK('G', "graph-funcs", &ftrace.graph_funcs, "func",
-"Set graph filter on given functions", parse_filter_func),
+"trace given functions using function_graph tracer",
+parse_filter_func),
  

[PATCH v6 00/17] perf: ftrace enhancement

2020-07-17 Thread Changbin Du
The perf has basic kernel ftrace support but lack support of most tracing
options. This serias is target to enhance the perf ftrace functionality so
that we can make full use of kernel ftrace with perf.

In general, this serias be cataloged into two main changes:
  1) Improve usability of existing functions. For example, we don't need to type
 extra option to select the tracer.
  2) Add new options to support all other ftrace functions.

Here is a glance of all ftrace functions with this serias:

$ sudo perf ftrace -h

 Usage: perf ftrace [] []
or: perf ftrace [] --  []

-a, --all-cpussystem-wide collection from all CPUs
-C, --cpulist of cpus to monitor
-D, --delayms to wait before starting tracing after program start
-F, --funcs   Show available functions to filter
-G, --graph-funcs 
  trace given functions using function_graph tracer
-g, --nograph-funcs 
  Set nograph filter on given functions
-m, --buffer-size 
  size of per cpu buffer
-N, --notrace-funcs 
  do not trace given functions
-p, --pidtrace on existing process id
-T, --trace-funcs 
  trace given functions using function tracer
-t, --tracer 
  tracer to use: function or function_graph (This 
option is deprecated)
-v, --verbose be more verbose
--func-opts 
  function tracer options, available options: 
call-graph,irq-info
--graph-opts 
  graph tracer options, available options: 
nosleep-time,noirqs,verbose,thresh=,depth=
--inherit trace children processes

v6:
  o fix return value of read_tracing_file_to_stdout().
  o make __cmd_ftrace() shorter.
  o remove option '-t, --tid '.
v5:
  o trivial fixes.
v4:
  o add util/parse-sublevel-options.c
  O remove -D/--graph-depth
v3:
  o add --func-opts and --graph-opts to set tracer specific options.
  o support units as a suffix for option '-m/--buffer-size'.
v2:
  o patches for option '-u/--userstacktrace' and '--no-pager' are dropped.
  o update all related perf documentation.
  o rename some options. Now all funcgraph tracer options are prefixed with
'--graph-', while all function tracer options are prefixed with '--func-'.
  o mark old options deprecated instead of removing them.


Changbin Du (17):
  perf ftrace: select function/function_graph tracer automatically
  perf ftrace: add option '-F/--funcs' to list available functions
  perf ftrace: factor out function write_tracing_file_int()
  perf ftrace: add option '-m/--buffer-size' to set per-cpu buffer size
  perf ftrace: show trace column header
  perf ftrace: add option '--inherit' to trace children processes
  perf: util: add general function to parse sublevel options
  perf ftrace: add support for tracing option 'func_stack_trace'
  perf ftrace: add support for trace option sleep-time
  perf ftrace: add support for trace option funcgraph-irqs
  perf ftrace: add support for tracing option 'irq-info'
  perf ftrace: add option 'verbose' to show more info for graph tracer
  perf ftrace: add support for trace option tracing_thresh
  perf: ftrace: allow set graph depth by '--graph-opts'
  perf ftrace: add option -D/--delay to delay tracing
  perf: ftrace: Add set_tracing_options() to set all trace options
  perf ftrace: add change log

 tools/perf/Documentation/perf-config.txt |   5 -
 tools/perf/Documentation/perf-ftrace.txt |  33 +-
 tools/perf/builtin-ftrace.c  | 412 +--
 tools/perf/util/Build|   1 +
 tools/perf/util/debug.c  |  61 +---
 tools/perf/util/parse-sublevel-options.c |  70 
 tools/perf/util/parse-sublevel-options.h |  11 +
 7 files changed, 507 insertions(+), 86 deletions(-)
 create mode 100644 tools/perf/util/parse-sublevel-options.c
 create mode 100644 tools/perf/util/parse-sublevel-options.h

-- 
2.25.1



Re: [PATCH v5 07/17] perf ftrace: add option '--inherit' to trace children processes

2020-07-17 Thread Changbin Du
On Mon, Jul 13, 2020 at 10:59:56AM +0900, Namhyung Kim wrote:
> On Sat, Jul 11, 2020 at 9:42 PM Changbin Du  wrote:
> >
> > This adds an option '--inherit' to allow us trace children
> > processes spawned by our target.
> >
> > Signed-off-by: Changbin Du 
> >
> > ---
> > v2: option name '--trace-children' -> '--inherit'.
> > ---
> >  tools/perf/Documentation/perf-ftrace.txt |  3 ++
> >  tools/perf/builtin-ftrace.c  | 38 
> >  2 files changed, 41 insertions(+)
> >
> > diff --git a/tools/perf/Documentation/perf-ftrace.txt 
> > b/tools/perf/Documentation/perf-ftrace.txt
> > index 98fe01d354d1..fd632bd9b2c1 100644
> > --- a/tools/perf/Documentation/perf-ftrace.txt
> > +++ b/tools/perf/Documentation/perf-ftrace.txt
> > @@ -61,6 +61,9 @@ OPTIONS
> > Set the size of per-cpu tracing buffer,  is expected to
> > be a number with appended unit character - B/K/M/G.
> >
> > +--inherit::
> > +   Trace children processes spawned by our target.
> > +
> >  -T::
> >  --trace-funcs=::
> > Only trace functions given by the argument.  Multiple functions
> > diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
> > index 887e78b23a82..4efaa7b6a906 100644
> > --- a/tools/perf/builtin-ftrace.c
> > +++ b/tools/perf/builtin-ftrace.c
> > @@ -39,6 +39,7 @@ struct perf_ftrace {
> > struct list_headnograph_funcs;
> > int graph_depth;
> > unsigned long   percpu_buffer_size;
> > +   boolinherit;
> >  };
> >
> >  struct filter_entry {
> > @@ -177,9 +178,27 @@ static int write_tracing_file_int(const char *name, 
> > int value)
> > return 0;
> >  }
> >
> > +static int write_tracing_option_file(const char *name, const char *val)
> > +{
> > +   char *file;
> > +   int ret;
> > +
> > +   if (asprintf(&file, "options/%s", name) < 0)
> > +   return -1;
> > +
> > +   ret = __write_tracing_file(file, val, false);
> > +   free(file);
> > +   return ret;
> > +}
> > +
> >  static int reset_tracing_cpu(void);
> >  static void reset_tracing_filters(void);
> >
> > +static void reset_tracing_options(struct perf_ftrace *ftrace 
> > __maybe_unused)
> > +{
> > +   write_tracing_option_file("function-fork", "0");
> > +}
> > +
> >  static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
> >  {
> > if (write_tracing_file("tracing_on", "0") < 0)
> > @@ -198,6 +217,7 @@ static int reset_tracing_files(struct perf_ftrace 
> > *ftrace __maybe_unused)
> > return -1;
> >
> > reset_tracing_filters();
> > +   reset_tracing_options(ftrace);
> > return 0;
> >  }
> >
> > @@ -336,6 +356,17 @@ static int set_tracing_percpu_buffer_size(struct 
> > perf_ftrace *ftrace)
> > return 0;
> >  }
> >
> > +static int set_tracing_trace_inherit(struct perf_ftrace *ftrace)
> > +{
> > +   if (!ftrace->inherit)
> > +   return 0;
> > +
> > +   if (write_tracing_option_file("function-fork", "1") < 0)
> > +   return -1;
> > +
> > +   return 0;
> > +}
> > +
> >  static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
> > **argv)
> >  {
> > char *trace_file;
> > @@ -405,6 +436,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, 
> > int argc, const char **argv)
> > goto out_reset;
> > }
> >
> > +   if (set_tracing_trace_inherit(ftrace) < 0) {
> > +   pr_err("failed to set tracing option function-fork\n");
> > +   goto out_reset;
> > +   }
> 
> Can we have set_tracing_options() here instead to make
> the __cmd_ftrace() shorter?  It'd set other options added later.
> It's also symmetric to reset_tracing_options().
>
I appended a patch to do this. Thanks for your suggestion.

> Thanks
> Namhyung
> 
> > +
> > if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
> > pr_err("failed to set current_tracer to %s\n", 
> > ftrace->tracer);
> > goto out_reset;
> > @@ -599,6 +635,8 @@ int cmd_ftrace(int argc, const char **argv)
> > "Max depth for function graph tracer"),
> > OPT_CALLBACK('m', "buffer-size", &ftrace.percpu_buffer_size, "size",
> >  "size of per cpu buffer", parse_buffer_size),
> > +   OPT_BOOLEAN(0, "inherit", &ftrace.inherit,
> > +   "trace children processes"),
> > OPT_END()
> > };
> >
> > --
> > 2.25.1
> >

-- 
Cheers,
Changbin Du


Re: [PATCH v5 13/17] perf ftrace: add option 'verbose' to show more info for graph tracer

2020-07-17 Thread Changbin Du
On Mon, Jul 13, 2020 at 11:07:56AM +0900, Namhyung Kim wrote:
> On Sat, Jul 11, 2020 at 9:43 PM Changbin Du  wrote:
> >
> > Sometimes we want ftrace display more and longer information about
> > the trace.
> >
> > $ sudo perf ftrace -G
> >  2)   0.979 us|  mutex_unlock();
> >  2)   1.540 us|  __fsnotify_parent();
> >  2)   0.433 us|  fsnotify();
> >
> > $ sudo perf ftrace -G --graph-opts verbose
> 
> These -G option usage should be changed..
>
The commit mesge is update now. Thanks.

> Thanks
> Namhyung
> 
> 
> > 14160.770883 |   0)  <...>-47814   |   |   1.289 us|  
> > mutex_unlock();
> > 14160.770886 |   0)  <...>-47814   |   |   1.624 us|  
> > __fsnotify_parent();
> > 14160.770887 |   0)  <...>-47814   |   |   0.636 us|  fsnotify();
> > 14160.770888 |   0)  <...>-47814   |   |   0.328 us|  
> > __sb_end_write();
> > 14160.770888 |   0)  <...>-47814   |  d... |   0.430 us|  
> > fpregs_assert_state_consistent();
> > 14160.770889 |   0)  <...>-47814   |  d... |   |  
> > do_syscall_64() {
> > 14160.770889 |   0)  <...>-47814   |   |   |
> > __x64_sys_close() {
> >
> > Signed-off-by: Changbin Du 
> > ---
> >  tools/perf/Documentation/perf-ftrace.txt |  1 +
> >  tools/perf/builtin-ftrace.c  | 29 +++-
> >  2 files changed, 29 insertions(+), 1 deletion(-)
> >
> > diff --git a/tools/perf/Documentation/perf-ftrace.txt 
> > b/tools/perf/Documentation/perf-ftrace.txt
> > index e6e9564d6c2e..0dd5ef4f9c65 100644
> > --- a/tools/perf/Documentation/perf-ftrace.txt
> > +++ b/tools/perf/Documentation/perf-ftrace.txt
> > @@ -107,6 +107,7 @@ OPTIONS
> > List of options allowed to set:
> >   nosleep-time - Measure on-CPU time only for function_graph tracer.
> >   noirqs   - Ignore functions that happen inside interrupt.
> > + verbose  - Show process names, PIDs, timestamps, etc.
> >
> >  SEE ALSO
> >  
> > diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
> > index a5906258c413..d169d6329454 100644
> > --- a/tools/perf/builtin-ftrace.c
> > +++ b/tools/perf/builtin-ftrace.c
> > @@ -45,6 +45,7 @@ struct perf_ftrace {
> > int func_irq_info;
> > int graph_nosleep_time;
> > int graph_noirqs;
> > +   int graph_verbose;
> >  };
> >
> >  struct filter_entry {
> > @@ -205,6 +206,9 @@ static void reset_tracing_options(struct perf_ftrace 
> > *ftrace __maybe_unused)
> > write_tracing_option_file("func_stack_trace", "0");
> > write_tracing_option_file("sleep-time", "1");
> > write_tracing_option_file("funcgraph-irqs", "1");
> > +   write_tracing_option_file("funcgraph-proc", "0");
> > +   write_tracing_option_file("funcgraph-abstime", "0");
> > +   write_tracing_option_file("latency-format", "0");
> > write_tracing_option_file("irq-info", "0");
> >  }
> >
> > @@ -420,6 +424,23 @@ static int set_tracing_funcgraph_irqs(struct 
> > perf_ftrace *ftrace)
> > return 0;
> >  }
> >
> > +static int set_tracing_funcgraph_verbose(struct perf_ftrace *ftrace)
> > +{
> > +   if (!ftrace->graph_verbose)
> > +   return 0;
> > +
> > +   if (write_tracing_option_file("funcgraph-proc", "1") < 0)
> > +   return -1;
> > +
> > +   if (write_tracing_option_file("funcgraph-abstime", "1") < 0)
> > +   return -1;
> > +
> > +   if (write_tracing_option_file("latency-format", "1") < 0)
> > +   return -1;
> > +
> > +   return 0;
> > +}
> > +
> >  static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char 
> > **argv)
> >  {
> > char *trace_file;
> > @@ -514,6 +535,11 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, 
> > int argc, const char **argv)
> > goto out_reset;
> > }
> >
> > +   if (set_tracing_funcgraph_verbose(ftrace) < 0) {
> > +   pr_err("failed to set tracing option 
> > funcgraph-proc/funcgraph-abstime\n&quo

Re: [PATCH v5 02/17] perf ftrace: add option '-F/--funcs' to list available functions

2020-07-17 Thread Changbin Du
On Mon, Jul 13, 2020 at 10:49:40AM +0900, Namhyung Kim wrote:
> Hello,
> 
> On Sat, Jul 11, 2020 at 9:42 PM Changbin Du  wrote:
> >
> > This adds an option '-F/--funcs' to list all available functions to trace,
> > which is read from tracing file 'available_filter_functions'.
> >
> > $ sudo ./perf ftrace -F | head
> > trace_initcall_finish_cb
> > initcall_blacklisted
> > do_one_initcall
> > do_one_initcall
> > trace_initcall_start_cb
> > run_init_process
> > try_to_run_init_process
> > match_dev_by_label
> > match_dev_by_uuid
> > rootfs_init_fs_context
> >
> > Signed-off-by: Changbin Du 
> >
> > ---
> > v2: option name '-l/--list-functions' -> '-F/--funcs'
> > ---
> >  tools/perf/Documentation/perf-ftrace.txt |  4 +++
> >  tools/perf/builtin-ftrace.c  | 43 
> >  2 files changed, 47 insertions(+)
> >
> > diff --git a/tools/perf/Documentation/perf-ftrace.txt 
> > b/tools/perf/Documentation/perf-ftrace.txt
> > index 952e46669168..d79560dea19f 100644
> > --- a/tools/perf/Documentation/perf-ftrace.txt
> > +++ b/tools/perf/Documentation/perf-ftrace.txt
> > @@ -30,6 +30,10 @@ OPTIONS
> >  --verbose=::
> >  Verbosity level.
> >
> > +-F::
> > +--funcs::
> > +List all available functions to trace.
> > +
> >  -p::
> >  --pid=::
> > Trace on existing process id (comma separated list).
> > diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
> > index 5f53da87040d..244cc8e6bd60 100644
> > --- a/tools/perf/builtin-ftrace.c
> > +++ b/tools/perf/builtin-ftrace.c
> > @@ -32,6 +32,7 @@ struct perf_ftrace {
> > struct evlist   *evlist;
> > struct target   target;
> > const char  *tracer;
> > +   boollist_avail_functions;
> > struct list_headfilters;
> > struct list_headnotrace;
> > struct list_headgraph_funcs;
> > @@ -127,6 +128,43 @@ static int append_tracing_file(const char *name, const 
> > char *val)
> > return __write_tracing_file(name, val, true);
> >  }
> >
> > +static int read_tracing_file_to_stdout(const char *name)
> > +{
> > +   char buf[4096];
> > +   char *file;
> > +   int fd;
> > +   int ret = -1;
> > +
> > +   file = get_tracing_file(name);
> > +   if (!file) {
> > +   pr_debug("cannot get tracing file: %s\n", name);
> > +   return -1;
> > +   }
> > +
> > +   fd = open(file, O_RDONLY);
> > +   if (fd < 0) {
> > +   pr_debug("cannot open tracing file: %s: %s\n",
> > +name, str_error_r(errno, buf, sizeof(buf)));
> > +   goto out;
> > +   }
> > +
> > +   /* read contents to stdout */
> > +   while (true) {
> > +   int n = read(fd, buf, sizeof(buf));
> > +   if (n <= 0)
> > +   goto out_close;
> > +   if (fwrite(buf, n, 1, stdout) != 1)
> > +   goto out_close;
> > +   }
> > +   ret = 0;
> 
> As I said before, there's no break in the loop above
> so the ret can never be 0.
>
I see now. Just fixed it as:
while (true) {
int n = read(fd, buf, sizeof(buf));
-   if (n <= 0)
+   if (n == 0)
+   break;
+   else if (n < 0)
goto out_close;
+

Thanks!

> Thanks
> Namhyung
> 
> > +
> > +out_close:
> > +   close(fd);
> > +out:
> > +   put_tracing_file(file);
> > +   return ret;
> > +}
> > +
> >  static int reset_tracing_cpu(void);
> >  static void reset_tracing_filters(void);
> >
> > @@ -301,6 +339,9 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int 
> > argc, const char **argv)
> > signal(SIGCHLD, sig_handler);
> > signal(SIGPIPE, sig_handler);
> >
> > +   if (ftrace->list_avail_functions)
> > +   return 
> > read_tracing_file_to_stdout("available_filter_functions");
> > +
> > if (reset_tracing_files(ftrace) < 0) {
> > pr_err("failed to reset ftrace\n");
> > goto out;
> > @@ -470,6 +511,8 @@ int cmd_ftrace(int argc, const char **argv)
> > const struct option ftrace_options[] = {
> > OPT_STRING('t', "tracer", &ftrace.tracer, "tracer",
> >"tracer to use: function or function_graph (This option 
> > is deprecated)"),
> > +   OPT_BOOLEAN('F', "funcs", &ftrace.list_avail_functions,
> > +   "Show available functions to filter"),
> > OPT_STRING('p', "pid", &ftrace.target.pid, "pid",
> >"trace on existing process id"),
> > OPT_INCR('v', "verbose", &verbose,
> > --
> > 2.25.1
> >

-- 
Cheers,
Changbin Du


Re: [PATCH v5 03/17] perf ftrace: add option -t/--tid to filter by thread id

2020-07-17 Thread Changbin Du
On Thu, Jul 16, 2020 at 12:36:30PM -0300, Arnaldo Carvalho de Melo wrote:
> Em Sat, Jul 11, 2020 at 08:40:21PM +0800, Changbin Du escreveu:
> > This allows us to trace single thread instead of the whole process.
> > 
> > Signed-off-by: Changbin Du 
> > ---
> >  tools/perf/Documentation/perf-ftrace.txt | 4 
> >  tools/perf/builtin-ftrace.c  | 2 ++
> >  2 files changed, 6 insertions(+)
> > 
> > diff --git a/tools/perf/Documentation/perf-ftrace.txt 
> > b/tools/perf/Documentation/perf-ftrace.txt
> > index d79560dea19f..e204bf6d50d8 100644
> > --- a/tools/perf/Documentation/perf-ftrace.txt
> > +++ b/tools/perf/Documentation/perf-ftrace.txt
> > @@ -38,6 +38,10 @@ OPTIONS
> >  --pid=::
> > Trace on existing process id (comma separated list).
> >  
> > +-t::
> > +--tid=::
> > +   Trace on existing thread id (comma separated list).
> > +
> 
> 
> Humm, I just  tried:
> 
> [root@five ~]# yes > /dev/null &
> [1] 18265
> [root@five ~]# perf ftrace --tid 18265
> ^C[root@five ~]#
> 
> After waiting for a while, nothing, what am I doing wrong?
>
I got it wrong. Currently ftrace only can filter by pid. If the pid is not
the main thread it won't work.

So this patch makes no sense. will drop this.

> - Arnaldo
> 
> 
> >  -a::
> >  --all-cpus::
> > Force system-wide collection.  Scripts run without a 
> > diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
> > index 244cc8e6bd60..1188b82c6541 100644
> > --- a/tools/perf/builtin-ftrace.c
> > +++ b/tools/perf/builtin-ftrace.c
> > @@ -515,6 +515,8 @@ int cmd_ftrace(int argc, const char **argv)
> > "Show available functions to filter"),
> > OPT_STRING('p', "pid", &ftrace.target.pid, "pid",
> >"trace on existing process id"),
> > +   OPT_STRING('t', "tid", &ftrace.target.tid, "tid",
> > +  "trace on existing thread id (exclusive to --pid)"),
> > OPT_INCR('v', "verbose", &verbose,
> >  "be more verbose"),
> > OPT_BOOLEAN('a', "all-cpus", &ftrace.target.system_wide,
> > -- 
> > 2.25.1
> > 
> 
> -- 
> 
> - Arnaldo

-- 
Cheers,
Changbin Du


  1   2   3   4   5   6   7   >