perf tools: Restore proper cwd on return from mnt ns
Jiri Olsa
reviewerPATCH 1/1 perf tools: Restore proper cwd on return from mnt ns
When reporting on 'record' server we try to retrieve/use the mnt namespace of the profiled tasks. We use following API with cookie to hold the return namespace, roughly:
nsinfo__mountns_enter(struct nsinfo *nsi, struct nscookie *nc)
setns(newns, 0);
...
new ns related open..
...
nsinfo__mountns_exit(struct nscookie *nc)
setns(nc->oldns)Once finished we setns to old namespace, which also sets the current working directory (cwd) to "/", trashing the cwd we had.
This is mostly fine, because we use absolute paths almost everywhere, but it screws up perf diff:
# perf diff failed to open perf.data: No such file or directory (try 'perf record' first) ...
Adding the current working directory to be part of the cookie and restoring it in the nsinfo__mountns_exit call.
--- tools/perf/util/namespaces.c | 18 ++++++++++++++++-- tools/perf/util/namespaces.h | 1 + 2 files changed, 17 insertions(+), 2 deletions(-)
tools/perf/util/namespaces.c +16 -2
@@ -18,6 +18,7 @@#include <stdio.h> #include <string.h> #include <unistd.h> +#include <asm/bug.h> struct namespaces *namespaces__new (struct namespaces_event *event) {
@@ -186,6 +187,7 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,char curpath[PATH_MAX ];int oldns =-1 ;int newns =-1 ; +char *oldcwd =NULL ;if (nc ==NULL )return ;
@@ -199,9 +201,13 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,if (snprintf (curpath,PATH_MAX ,"/proc/self/ns/mnt" ) >=PATH_MAX )return ; + oldcwd =get_current_dir_name (); +if (!oldcwd) +return ; + oldns =open (curpath,O_RDONLY );if (oldns <0 ) -return ; + goto errout; newns =open (nsi->mntns_path,O_RDONLY );if (newns <0 )
@@ -210,11 +216,14 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,if (setns (newns,CLONE_NEWNS ) <0 ) goto errout; + nc->oldcwd = oldcwd; nc->oldns = oldns; nc->newns = newns;return ; errout: +if (oldcwd) +free (oldcwd);if (oldns >-1 )close (oldns);if (newns >-1 )
@@ -223,11 +232,16 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,void nsinfo__mountns_exit (struct nscookie *nc) { -if (nc ==NULL || nc->oldns ==-1 || nc->newns ==-1 ) +if (nc ==NULL || nc->oldns ==-1 || nc->newns ==-1 || !nc->oldcwd)return ;setns (nc->oldns,CLONE_NEWNS ); +if (nc->oldcwd) { +WARN_ON_ONCE (chdir (nc->oldcwd)); +free (nc->oldcwd); + } +if (nc->oldns >-1 ) {close (nc->oldns); nc->oldns =-1 ;
tools/perf/util/namespaces.h +1 -0
@@ -38,6 +38,7 @@ struct nsinfo {struct nscookie {int oldns;int newns; +char *oldcwd; };int nsinfo__init (struct nsinfo *nsi);
Signature · 1 line
2.17.2
ping
jirka
Quoted 117 lines · Jiri Olsa
When reporting on 'record' server we try to retrieve/use the mnt namespace of the profiled tasks. We use following API with cookie to hold the return namespace, roughly:
nsinfo__mountns_enter(struct nsinfo *nsi, struct nscookie *nc)setns(newns, 0); ... new ns related open.. ... nsinfo__mountns_exit(struct nscookie *nc) setns(nc->oldns)Once finished we setns to old namespace, which also sets the current working directory (cwd) to "/", trashing the cwd we had.
This is mostly fine, because we use absolute paths almost everywhere, but it screws up perf diff:
# perf diff failed to open perf.data: No such file or directory (try 'perf record' first) ...Adding the current working directory to be part of the cookie and restoring it in the
nsinfo__mountns_exitcall.Cc Krister Johansen <[email protected]>Fixes 843ff37bb59e ("perf symbols: Find symbols in different mount namespace")Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/util/namespaces.c | 18 ++++++++++++++++-- tools/perf/util/namespaces.h | 1 + 2 files changed, 17 insertions(+), 2 deletions(-)tools/perf/util/namespaces.c +16
-2@@ -18,6 +18,7 @@#include <stdio.h> #include <string.h> #include <unistd.h> +#include <asm/bug.h> struct namespaces *namespaces__new (struct namespaces_event *event) {@@ -186,6 +187,7 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,char curpath[PATH_MAX ];int oldns =-1 ;int newns =-1 ; +char *oldcwd =NULL ;if (nc ==NULL )return ;@@ -199,9 +201,13 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,if (snprintf (curpath,PATH_MAX ,"/proc/self/ns/mnt" ) >=PATH_MAX )return ; + oldcwd =get_current_dir_name (); +if (!oldcwd) +return ; + oldns =open (curpath,O_RDONLY );if (oldns <0 ) -return ; + goto errout; newns =open (nsi->mntns_path,O_RDONLY );if (newns <0 )@@ -210,11 +216,14 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,if (setns (newns,CLONE_NEWNS ) <0 ) goto errout; + nc->oldcwd = oldcwd; nc->oldns = oldns; nc->newns = newns;return ; errout: +if (oldcwd) +free (oldcwd);if (oldns >-1 )close (oldns);if (newns >-1 )@@ -223,11 +232,16 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,void nsinfo__mountns_exit (struct nscookie *nc) { -if (nc ==NULL || nc->oldns ==-1 || nc->newns ==-1 ) +if (nc ==NULL || nc->oldns ==-1 || nc->newns ==-1 || !nc->oldcwd)return ;setns (nc->oldns,CLONE_NEWNS ); +if (nc->oldcwd) { +WARN_ON_ONCE (chdir (nc->oldcwd)); +free (nc->oldcwd); + } +if (nc->oldns >-1 ) {close (nc->oldns); nc->oldns =-1 ;tools/perf/util/namespaces.h +1
-0@@ -38,6 +38,7 @@ struct nsinfo {struct nscookie {int oldns;int newns; +char *oldcwd; };int nsinfo__init (struct nsinfo *nsi);Signature · 1 line
2.17.2
Em Thu, Nov 01, 2018 at 06:00:01PM +0100, Jiri Olsa escreveu:
Quoted 71 lines
When reporting on 'record' server we try to retrieve/use the mnt namespace of the profiled tasks. We use following API with cookie to hold the return namespace, roughly:
nsinfo__mountns_enter(struct nsinfo *nsi, struct nscookie *nc)setns(newns, 0); ... new ns related open.. ... nsinfo__mountns_exit(struct nscookie *nc) setns(nc->oldns)Once finished we setns to old namespace, which also sets the current working directory (cwd) to "/", trashing the cwd we had.
This is mostly fine, because we use absolute paths almost everywhere, but it screws up perf diff:
# perf diff failed to open perf.data: No such file or directory (try 'perf record' first) ...Adding the current working directory to be part of the cookie and restoring it in the
nsinfo__mountns_exitcall.Cc Krister Johansen <[email protected]>Fixes 843ff37bb59e ("perf symbols: Find symbols in different mount namespace")Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/util/namespaces.c | 18 ++++++++++++++++-- tools/perf/util/namespaces.h | 1 + 2 files changed, 17 insertions(+), 2 deletions(-)tools/perf/util/namespaces.c +7
-1@@ -18,6 +18,7 @@#include <stdio.h> #include <string.h> #include <unistd.h> +#include <asm/bug.h> struct namespaces *namespaces__new (struct namespaces_event *event) {@@ -186,6 +187,7 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,char curpath[PATH_MAX ];int oldns =-1 ;int newns =-1 ; +char *oldcwd =NULL ;if (nc ==NULL )return ;@@ -199,9 +201,13 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,if (snprintf (curpath,PATH_MAX ,"/proc/self/ns/mnt" ) >=PATH_MAX )return ; + oldcwd =get_current_dir_name (); +if (!oldcwd) +return ; + oldns =open (curpath,O_RDONLY );if (oldns <0 ) -return ; + goto errout; newns =open (nsi->mntns_path,O_RDONLY );if (newns <0 )@@ -210,11 +216,14 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,if (setns (newns,CLONE_NEWNS ) <0 )
tools/perf/util/namespaces.c void nsinfo__mountns_enter(struct nsinfo *nsi, · line 226
Quoted 10 lines
tools/perf/util/namespaces.c +3
-0goto errout; + nc->oldcwd = oldcwd; nc->oldns = oldns; nc->newns = newns;return ; errout: +if (oldcwd) +free (oldcwd);
Applied, and while at it I removed the needless if in the above two lines.
Quoted 35 lines
tools/perf/util/namespaces.c +6
-1if (oldns >-1 )close (oldns);if (newns >-1 )@@ -223,11 +232,16 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,void nsinfo__mountns_exit (struct nscookie *nc) { -if (nc ==NULL || nc->oldns ==-1 || nc->newns ==-1 ) +if (nc ==NULL || nc->oldns ==-1 || nc->newns ==-1 || !nc->oldcwd)return ;setns (nc->oldns,CLONE_NEWNS ); +if (nc->oldcwd) { +WARN_ON_ONCE (chdir (nc->oldcwd)); +free (nc->oldcwd); + } +if (nc->oldns >-1 ) {close (nc->oldns); nc->oldns =-1 ;tools/perf/util/namespaces.h +1
-0@@ -38,6 +38,7 @@ struct nsinfo {struct nscookie {int oldns;int newns; +char *oldcwd; };int nsinfo__init (struct nsinfo *nsi);Signature · 1 line
2.17.2
Arnaldo Carvalho de Melo
maintainerEm Fri, Nov 16, 2018 at 10:31:43AM -0800, Arnaldo Carvalho de Melo escreveu:
Quoted 97 lines
Em Thu, Nov 01, 2018 at 06:00:01PM +0100, Jiri Olsa escreveu:
Quoted 71 lines
When reporting on 'record' server we try to retrieve/use the mnt namespace of the profiled tasks. We use following API with cookie to hold the return namespace, roughly:
nsinfo__mountns_enter(struct nsinfo *nsi, struct nscookie *nc)setns(newns, 0); ... new ns related open.. ... nsinfo__mountns_exit(struct nscookie *nc) setns(nc->oldns)Once finished we setns to old namespace, which also sets the current working directory (cwd) to "/", trashing the cwd we had.
This is mostly fine, because we use absolute paths almost everywhere, but it screws up perf diff:
# perf diff failed to open perf.data: No such file or directory (try 'perf record' first) ...Adding the current working directory to be part of the cookie and restoring it in the
nsinfo__mountns_exitcall.Cc Krister Johansen <[email protected]>Fixes 843ff37bb59e ("perf symbols: Find symbols in different mount namespace")Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/util/namespaces.c | 18 ++++++++++++++++-- tools/perf/util/namespaces.h | 1 + 2 files changed, 17 insertions(+), 2 deletions(-)tools/perf/util/namespaces.c +7
-1@@ -18,6 +18,7 @@#include <stdio.h> #include <string.h> #include <unistd.h> +#include <asm/bug.h> struct namespaces *namespaces__new (struct namespaces_event *event) {@@ -186,6 +187,7 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,char curpath[PATH_MAX ];int oldns =-1 ;int newns =-1 ; +char *oldcwd =NULL ;if (nc ==NULL )return ;@@ -199,9 +201,13 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,if (snprintf (curpath,PATH_MAX ,"/proc/self/ns/mnt" ) >=PATH_MAX )return ; + oldcwd =get_current_dir_name (); +if (!oldcwd) +return ; + oldns =open (curpath,O_RDONLY );if (oldns <0 ) -return ; + goto errout; newns =open (nsi->mntns_path,O_RDONLY );if (newns <0 )@@ -210,11 +216,14 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,if (setns (newns,CLONE_NEWNS ) <0 )tools/perf/util/namespaces.c void nsinfo__mountns_enter(struct nsinfo *nsi, · line 226
Quoted 10 lines
tools/perf/util/namespaces.c +3
-0goto errout; + nc->oldcwd = oldcwd; nc->oldns = oldns; nc->newns = newns;return ; errout: +if (oldcwd) +free (oldcwd);Applied, and while at it I removed the needless if in the above two lines.
Quoted 11 lines
tools/perf/util/namespaces.c +1
-1if (oldns >-1 )close (oldns);if (newns >-1 )@@ -223,11 +232,16 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,void nsinfo__mountns_exit (struct nscookie *nc) { -if (nc ==NULL || nc->oldns ==-1 || nc->newns ==-1 ) +if (nc ==NULL || nc->oldns ==-1 || nc->newns ==-1 || !nc->oldcwd)return ;
Quoted 7 lines
tools/perf/util/namespaces.c void nsinfo__mountns_enter(struct nsinfo *nsi, · line 244
Quoted 7 lines
tools/perf/util/namespaces.c +5
-0setns (nc->oldns,CLONE_NEWNS ); +if (nc->oldcwd) { +WARN_ON_ONCE (chdir (nc->oldcwd)); +free (nc->oldcwd); + } +
Also changed the above to zfree(&nc->oldcwd) as this is in a struct member, that is not freed by the freeing caller (nsinfo__mountns_exit()), to avoid later possible use-after-free (I haven't checked if it _actually_ happens with the current codebase, but it could) also to match the following block, where the resource is released and then the handler is invalidated.
- Arnaldo
Quoted 3 lines
Quoted 3 lines
tools/perf/util/namespaces.c +0
-0if (nc->oldns >-1 ) {close (nc->oldns); nc->oldns =-1 ;
Quoted 75 lines · Arnaldo Carvalho de Melo
Em Fri, Nov 16, 2018 at 10:31:43AM -0800, Arnaldo Carvalho de Melo escreveu:
Quoted 74 lines
Em Thu, Nov 01, 2018 at 06:00:01PM +0100, Jiri Olsa escreveu:
Quoted 73 lines
When reporting on 'record' server we try to retrieve/use the mnt namespace of the profiled tasks. We use following API with cookie to hold the return namespace, roughly:
nsinfo__mountns_enter(struct nsinfo *nsi, struct nscookie *nc)setns(newns, 0); ... new ns related open.. ... nsinfo__mountns_exit(struct nscookie *nc) setns(nc->oldns)Once finished we setns to old namespace, which also sets the current working directory (cwd) to "/", trashing the cwd we had.
This is mostly fine, because we use absolute paths almost everywhere, but it screws up perf diff:
# perf diff failed to open perf.data: No such file or directory (try 'perf record' first) ...Adding the current working directory to be part of the cookie and restoring it in the
nsinfo__mountns_exitcall.Cc Krister Johansen <[email protected]>Fixes 843ff37bb59e ("perf symbols: Find symbols in different mount namespace")Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/util/namespaces.c | 18 ++++++++++++++++-- tools/perf/util/namespaces.h | 1 + 2 files changed, 17 insertions(+), 2 deletions(-)tools/perf/util/namespaces.c +7
-1@@ -18,6 +18,7 @@#include <stdio.h> #include <string.h> #include <unistd.h> +#include <asm/bug.h> struct namespaces *namespaces__new (struct namespaces_event *event) {@@ -186,6 +187,7 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,char curpath[PATH_MAX ];int oldns =-1 ;int newns =-1 ; +char *oldcwd =NULL ;if (nc ==NULL )return ;@@ -199,9 +201,13 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,if (snprintf (curpath,PATH_MAX ,"/proc/self/ns/mnt" ) >=PATH_MAX )return ; + oldcwd =get_current_dir_name (); +if (!oldcwd) +return ; + oldns =open (curpath,O_RDONLY );if (oldns <0 ) -return ; + goto errout; newns =open (nsi->mntns_path,O_RDONLY );if (newns <0 )@@ -210,11 +216,14 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,if (setns (newns,CLONE_NEWNS ) <0 ) goto errout;
Quoted 8 lines
Quoted 8 lines
tools/perf/util/namespaces.c void nsinfo__mountns_enter(struct nsinfo *nsi, · line 226
Quoted 8 lines
tools/perf/util/namespaces.c +3
-0+ nc->oldcwd = oldcwd; nc->oldns = oldns; nc->newns = newns;return ; errout: +if (oldcwd) +free (oldcwd);
right, ok
Quoted 17 lines
Quoted 17 lines
Applied, and while at it I removed the needless if in the above two lines.
Quoted 13 lines
tools/perf/util/namespaces.c +1
-1if (oldns >-1 )close (oldns);if (newns >-1 )@@ -223,11 +232,16 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,void nsinfo__mountns_exit (struct nscookie *nc) { -if (nc ==NULL || nc->oldns ==-1 || nc->newns ==-1 ) +if (nc ==NULL || nc->oldns ==-1 || nc->newns ==-1 || !nc->oldcwd)return ;setns (nc->oldns,CLONE_NEWNS );
Quoted 12 lines
Quoted 5 lines
tools/perf/util/namespaces.c void nsinfo__mountns_enter(struct nsinfo *nsi, · line 244
Quoted 5 lines
tools/perf/util/namespaces.c +5
-0+if (nc->oldcwd) { +WARN_ON_ONCE (chdir (nc->oldcwd)); +free (nc->oldcwd); + } +Also changed the above to
zfree(&nc->oldcwd)as this is in a struct member, that is not freed by the freeing caller (nsinfo__mountns_exit()), to avoid later possible use-after-free (I haven't checked if it _actually_ happens with the current codebase, but it could) also to match the following block, where the resource is released and then the handler is invalidated.
great, thanks
jirka
Arnaldo Carvalho de Melo
maintainerEm Thu, Nov 01, 2018 at 06:00:01PM +0100, Jiri Olsa escreveu:
tools/perf/util/namespaces.c void nsinfo__mountns_enter(struct nsinfo *nsi, · line 204
Quoted 13 lines
Adding the current working directory to be part of the cookie and restoring it in the
nsinfo__mountns_exitcall.tools/perf/util/namespaces.c +1
-0@@ -199,9 +201,13 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,if (snprintf (curpath,PATH_MAX ,"/proc/self/ns/mnt" ) >=PATH_MAX )return ; + oldcwd =get_current_dir_name ();
Breaks the build with bionic (Android), where get_current_dir_name() is not available:
/tmp/build/perf/libperf.a(libperf-in.o):hist.c:function nsinfo__mountns_enter: error: undefined reference to 'get_current_dir_name'
collect2: error: ld returned 1 exit status
Makefile.perf:534: recipe for target '/tmp/build/perf/perf' failed
make[2]: *** [/tmp/build/perf/perf] Error 1
Makefile.perf:206: recipe for target 'sub-make' failed
make[1]: *** [sub-make] Error 2
Makefile:69: recipe for target 'all' failed
make: *** [all] Error 2
make: Leaving directory '/git/linux/tools/perf'
[root@seventh ~]#
The container builds are ongoing, its possoble that this becomes an issue in uCLibc, wasn't on musl libc (Alpine Linux).
- Arnaldo
Quoted 29 lines · Arnaldo Carvalho de Melo
Em Thu, Nov 01, 2018 at 06:00:01PM +0100, Jiri Olsa escreveu:
tools/perf/util/namespaces.c void nsinfo__mountns_enter(struct nsinfo *nsi, · line 204
Quoted 13 lines
Adding the current working directory to be part of the cookie and restoring it in the
nsinfo__mountns_exitcall.tools/perf/util/namespaces.c +1
-0@@ -199,9 +201,13 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,if (snprintf (curpath,PATH_MAX ,"/proc/self/ns/mnt" ) >=PATH_MAX )return ; + oldcwd =get_current_dir_name ();Breaks the build with bionic (Android), where
get_current_dir_name()is not available:/tmp/build/perf/libperf.a(libperf-in.o):hist.c:function
nsinfo__mountns_enter: error: undefined reference to 'get_current_dir_name'
collect2: error: ld returned 1 exit status
Makefile.perf:534: recipe for target '/tmp/build/perf/perf' failed
make[2]: *** [/tmp/build/perf/perf] Error 1
Makefile.perf:206: recipe for target 'sub-make' failed
make[1]: *** [sub-make] Error 2
Makefile:69: recipe for target 'all' failed
make: *** [all] Error 2
make: Leaving directory '/git/linux/tools/perf'
[root@seventh ~]#
Quoted 2 lines
The container builds are ongoing, its possoble that this becomes an issue in uCLibc, wasn't on musl libc (Alpine Linux).
will check, thanks
jirka
PATCH v2 1/1 perf tools: Restore proper cwd on return from mnt ns
Quoted 30 lines · Jiri Olsa
Quoted 29 lines · Arnaldo Carvalho de Melo
Em Thu, Nov 01, 2018 at 06:00:01PM +0100, Jiri Olsa escreveu:
tools/perf/util/namespaces.c void nsinfo__mountns_enter(struct nsinfo *nsi, · line 204
Quoted 13 lines
Adding the current working directory to be part of the cookie and restoring it in the
nsinfo__mountns_exitcall.tools/perf/util/namespaces.c +1
-0@@ -199,9 +201,13 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,if (snprintf (curpath,PATH_MAX ,"/proc/self/ns/mnt" ) >=PATH_MAX )return ; + oldcwd =get_current_dir_name ();Breaks the build with bionic (Android), where
get_current_dir_name()is not available:/tmp/build/perf/libperf.a(libperf-in.o):hist.c:function
nsinfo__mountns_enter: error: undefined reference to 'get_current_dir_name'
collect2: error: ld returned 1 exit status
Makefile.perf:534: recipe for target '/tmp/build/perf/perf' failed
make[2]: *** [/tmp/build/perf/perf] Error 1
Makefile.perf:206: recipe for target 'sub-make' failed
make[1]: *** [sub-make] Error 2
Makefile:69: recipe for target 'all' failed
make: *** [all] Error 2
make: Leaving directory '/git/linux/tools/perf'
[root@seventh ~]#
Quoted 4 lines
Quoted 2 lines
The container builds are ongoing, its possoble that this becomes an issue in uCLibc, wasn't on musl libc (Alpine Linux).
will check, thanks
how about this one?
thanks,
jirka
---
When reporting on 'record' server we try to retrieve/use the mnt namespace of the profiled tasks. We use following API with cookie to hold the return namespace, roughly:
nsinfo__mountns_enter(struct nsinfo *nsi, struct nscookie *nc)
setns(newns, 0);
...
new ns related open..
...
nsinfo__mountns_exit(struct nscookie *nc)
setns(nc->oldns)Once finished we setns to old namespace, which also sets the current working directory (cwd) to "/", trashing the cwd we had.
This is mostly fine, because we use absolute paths almost everywhere, but it screws up perf diff:
# perf diff failed to open perf.data: No such file or directory (try 'perf record' first) ...
Adding the current working directory to be part of the cookie and restoring it in the nsinfo__mountns_exit call.
v2: get rid of _GNU_SOURCE get_current_dir_name call [acme]
--- tools/perf/util/namespaces.c | 25 +++++++++++++++++++++++-- tools/perf/util/namespaces.h | 1 + 2 files changed, 24 insertions(+), 2 deletions(-)
tools/perf/util/namespaces.c +23 -2
@@ -18,6 +18,7 @@#include <stdio.h> #include <string.h> #include <unistd.h> +#include <asm/bug.h> struct namespaces *namespaces__new (struct namespaces_event *event) {
@@ -180,12 +181,20 @@ void nsinfo__put(struct nsinfo *nsi)nsinfo__delete (nsi); } +static char *get_current_dir (void ) +{ +char path[PATH_MAX ]; + +return getcwd (path,PATH_MAX ) ?strdup (path) :NULL ; +} +void nsinfo__mountns_enter (struct nsinfo *nsi,struct nscookie *nc) {char curpath[PATH_MAX ];int oldns =-1 ;int newns =-1 ; +char *oldcwd =NULL ;if (nc ==NULL )return ;
@@ -199,9 +208,13 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,if (snprintf (curpath,PATH_MAX ,"/proc/self/ns/mnt" ) >=PATH_MAX )return ; + oldcwd =get_current_dir (); +if (!oldcwd) +return ; + oldns =open (curpath,O_RDONLY );if (oldns <0 ) -return ; + goto errout; newns =open (nsi->mntns_path,O_RDONLY );if (newns <0 )
@@ -210,11 +223,14 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,if (setns (newns,CLONE_NEWNS ) <0 ) goto errout; + nc->oldcwd = oldcwd; nc->oldns = oldns; nc->newns = newns;return ; errout: +if (oldcwd) +free (oldcwd);if (oldns >-1 )close (oldns);if (newns >-1 )
@@ -223,11 +239,16 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,void nsinfo__mountns_exit (struct nscookie *nc) { -if (nc ==NULL || nc->oldns ==-1 || nc->newns ==-1 ) +if (nc ==NULL || nc->oldns ==-1 || nc->newns ==-1 || !nc->oldcwd)return ;setns (nc->oldns,CLONE_NEWNS ); +if (nc->oldcwd) { +WARN_ON_ONCE (chdir (nc->oldcwd)); +free (nc->oldcwd); + } +if (nc->oldns >-1 ) {close (nc->oldns); nc->oldns =-1 ;
tools/perf/util/namespaces.h +1 -0
@@ -38,6 +38,7 @@ struct nsinfo {struct nscookie {int oldns;int newns; +char *oldcwd; };int nsinfo__init (struct nsinfo *nsi);
Signature · 1 line
2.17.2
Arnaldo Carvalho de Melo
maintainerEm Tue, Nov 20, 2018 at 11:56:18AM +0100, Jiri Olsa escreveu:
Quoted 30 lines · Arnaldo Carvalho de Melo
Quoted 29 lines
Em Thu, Nov 01, 2018 at 06:00:01PM +0100, Jiri Olsa escreveu:
tools/perf/util/namespaces.c void nsinfo__mountns_enter(struct nsinfo *nsi, · line 204
Quoted 13 lines
Adding the current working directory to be part of the cookie and restoring it in the
nsinfo__mountns_exitcall.tools/perf/util/namespaces.c +1
-0@@ -199,9 +201,13 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,if (snprintf (curpath,PATH_MAX ,"/proc/self/ns/mnt" ) >=PATH_MAX )return ; + oldcwd =get_current_dir_name ();Breaks the build with bionic (Android), where
get_current_dir_name()is not available:/tmp/build/perf/libperf.a(libperf-in.o):hist.c:function
nsinfo__mountns_enter: error: undefined reference to 'get_current_dir_name'
collect2: error: ld returned 1 exit status
Makefile.perf:534: recipe for target '/tmp/build/perf/perf' failed
make[2]: *** [/tmp/build/perf/perf] Error 1
Makefile.perf:206: recipe for target 'sub-make' failed
make[1]: *** [sub-make] Error 2
Makefile:69: recipe for target 'all' failed
make: *** [all] Error 2
make: Leaving directory '/git/linux/tools/perf'
[root@seventh ~]#
Quoted 4 lines
Quoted 2 lines
The container builds are ongoing, its possoble that this becomes an issue in uCLibc, wasn't on musl libc (Alpine Linux).
will check, thanks
I fixed this already, by adding a test for that get_current_dir_name() function and a simple implementation based on strdup(getcwd(bf)), take a look at my perf/urgent branch
- Arnaldo
Quoted 31 lines · Arnaldo Carvalho de Melo
Em Tue, Nov 20, 2018 at 11:56:18AM +0100, Jiri Olsa escreveu:
Quoted 30 lines · Arnaldo Carvalho de Melo
Quoted 29 lines
Em Thu, Nov 01, 2018 at 06:00:01PM +0100, Jiri Olsa escreveu:
tools/perf/util/namespaces.c void nsinfo__mountns_enter(struct nsinfo *nsi, · line 204
Quoted 13 lines
Adding the current working directory to be part of the cookie and restoring it in the
nsinfo__mountns_exitcall.tools/perf/util/namespaces.c +1
-0@@ -199,9 +201,13 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,if (snprintf (curpath,PATH_MAX ,"/proc/self/ns/mnt" ) >=PATH_MAX )return ; + oldcwd =get_current_dir_name ();Breaks the build with bionic (Android), where
get_current_dir_name()is not available:/tmp/build/perf/libperf.a(libperf-in.o):hist.c:function
nsinfo__mountns_enter: error: undefined reference to 'get_current_dir_name'
collect2: error: ld returned 1 exit status
Makefile.perf:534: recipe for target '/tmp/build/perf/perf' failed
make[2]: *** [/tmp/build/perf/perf] Error 1
Makefile.perf:206: recipe for target 'sub-make' failed
make[1]: *** [sub-make] Error 2
Makefile:69: recipe for target 'all' failed
make: *** [all] Error 2
make: Leaving directory '/git/linux/tools/perf'
[root@seventh ~]#
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
The container builds are ongoing, its possoble that this becomes an issue in uCLibc, wasn't on musl libc (Alpine Linux).
will check, thanks
I fixed this already, by adding a test for that
get_current_dir_name()function and a simple implementation based on strdup(getcwd(bf)), take a look at my perf/urgent branch
ok, I saw it.. but it seems little too much for a single function to me
jirka
tip-bot for Jiri Olsa
merge bot[tip:perf/urgent] perf tools: Restore proper cwd on return from mnt namespace
In reply to Jiri Olsaperf tools: Restore proper cwd on return from mnt namespace
Commit-ID: b01c1f69c8660eaeab7d365cd570103c5c073a02 Gitweb: https://git.kernel.org/tip/b01c1f69c8660eaeab7d365cd570103c5c073a02 Author: Jiri Olsa <[email protected]> AuthorDate: Thu, 1 Nov 2018 18:00:01 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Mon, 19 Nov 2018 12:12:26 -0800
perf tools: Restore proper cwd on return from mnt namespace
When reporting on 'record' server we try to retrieve/use the mnt namespace of the profiled tasks. We use following API with cookie to hold the return namespace, roughly:
nsinfo__mountns_enter(struct nsinfo *nsi, struct nscookie *nc)
setns(newns, 0);
...
new ns related open..
...
nsinfo__mountns_exit(struct nscookie *nc)
setns(nc->oldns)Once finished we setns to old namespace, which also sets the current working directory (cwd) to "/", trashing the cwd we had.
This is mostly fine, because we use absolute paths almost everywhere, but it screws up 'perf diff':
# perf diff failed to open perf.data: No such file or directory (try 'perf record' first) ...
Adding the current working directory to be part of the cookie and restoring it in the nsinfo__mountns_exit call.
--- tools/perf/util/namespaces.c | 17 +++++++++++++++-- tools/perf/util/namespaces.h | 1 + 2 files changed, 16 insertions(+), 2 deletions(-)
tools/perf/util/namespaces.c +15 -2
@@ -18,6 +18,7 @@#include <stdio.h> #include <string.h> #include <unistd.h> +#include <asm/bug.h> struct namespaces *namespaces__new (struct namespaces_event *event) {
@@ -186,6 +187,7 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,char curpath[PATH_MAX ];int oldns =-1 ;int newns =-1 ; +char *oldcwd =NULL ;if (nc ==NULL )return ;
@@ -199,9 +201,13 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,if (snprintf (curpath,PATH_MAX ,"/proc/self/ns/mnt" ) >=PATH_MAX )return ; + oldcwd =get_current_dir_name (); +if (!oldcwd) +return ; + oldns =open (curpath,O_RDONLY );if (oldns <0 ) -return ; + goto errout; newns =open (nsi->mntns_path,O_RDONLY );if (newns <0 )
@@ -210,11 +216,13 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,if (setns (newns,CLONE_NEWNS ) <0 ) goto errout; + nc->oldcwd = oldcwd; nc->oldns = oldns; nc->newns = newns;return ; errout: +free (oldcwd);if (oldns >-1 )close (oldns);if (newns >-1 )
@@ -223,11 +231,16 @@ errout:void nsinfo__mountns_exit (struct nscookie *nc) { -if (nc ==NULL || nc->oldns ==-1 || nc->newns ==-1 ) +if (nc ==NULL || nc->oldns ==-1 || nc->newns ==-1 || !nc->oldcwd)return ;setns (nc->oldns,CLONE_NEWNS ); +if (nc->oldcwd) { +WARN_ON_ONCE (chdir (nc->oldcwd)); +zfree (&nc->oldcwd); + } +if (nc->oldns >-1 ) {close (nc->oldns); nc->oldns =-1 ;
tools/perf/util/namespaces.h +1 -0
@@ -38,6 +38,7 @@ struct nsinfo {struct nscookie {int oldns;int newns; +char *oldcwd; };int nsinfo__init (struct nsinfo *nsi);