New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unable to find tracefs in different kernel so kernel tracing fails #1753
Comments
As written at #1471 (comment), the following example shows the clear usage. $ cat getmntent.c
#include <stdio.h>
#include <stdlib.h>
#include <mntent.h>
int main(void)
{
struct mntent *ent;
FILE *aFile;
aFile = setmntent("/proc/mounts", "r");
if (aFile == NULL) {
perror("setmntent");
exit(1);
}
while (NULL != (ent = getmntent(aFile))) {
printf("%s %s\n", ent->mnt_fsname, ent->mnt_dir);
}
endmntent(aFile);
} It can simply be compiled as follows.
Then the output shows it find
It also successfully finds the
|
I've seen issues #797, #1476, #1471(Comments-1) and the following is a list that needs to be checked again in the previous issues:
In conclusion, the above method using If there is no problem after reviewing the above, I'll try it. |
Hi @gichoel, Thanks a lot for the analysis. I've just tested that there is no problem compiling |
In order to solve this Issue, I thought that three conditions must be met in the code.
My code based on the above conditions are as follows. $ cat tracefs_unit_test.c
#define _GNU_SOURCE //for asprintf()
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <mntent.h>
#define true 1
#define false 0
#define PROC_MOUNTS_PATH "/proc/mounts"
#define TRACEFS_STR "tracefs"
#define DEBUGFS_STR "debugfs"
static char *TRACING_DIR = NULL;
enum TRACE_DIR_PRIORITY {
PRIORITY_FIRST = 0,
PRIORITY_SECOND,
PRIORITY_THIRD,
PRIORITY_NOT_ASSIGNED,
PRIORITY_END
};
int get_tracing_dir_priority(const char *tracing_dir_name) {
if( !strcmp(tracing_dir_name, TRACEFS_STR) ) { return PRIORITY_FIRST; }
else if ( !strcmp(tracing_dir_name, DEBUGFS_STR) ) { return PRIORITY_SECOND; }
return PRIORITY_NOT_ASSIGNED;
}
static int find_tracing_dir(void) {
struct mntent *ent;
FILE *fp;
/* open a file with the currently mounted list */
fp = setmntent(PROC_MOUNTS_PATH, "r");
if( fp == NULL ) {
printf("setmntent() return NULL\n");
return false;
}
/* compare if "tracefs" or "debugfs" exist in list mounted until EOF(End of File) */
while( NULL != (ent = getmntent(fp)) ) {
printf("%s : %s\n", ent->mnt_fsname, ent->mnt_dir);
if( !strcmp(ent->mnt_fsname, TRACEFS_STR) ||
!strcmp(ent->mnt_fsname, DEBUGFS_STR) )
{
if(TRACING_DIR != NULL) {
free(TRACING_DIR);
}
asprintf(&TRACING_DIR, "%s", ent->mnt_dir);
}
if( get_tracing_dir_priority(ent->mnt_fsname) == PRIORITY_FIRST ){
break;
}
}
/* close mntent fp */
endmntent(fp);
if(TRACING_DIR != NULL)
return true;
return false;
}
int main() {
if(find_tracing_dir() == true){
printf("\n");
printf("TRACING_DIR : %s\n", TRACING_DIR);
printf("\n");
}
return 0;
} It can simply be compiled as follows.
In my case (maybe it's because the results may vary depending on the OS), when I run the program, I get the result of finding tracefs normally even if debugfs exists first as shown below.
|
Hi @gichoel, thanks for your work. But I started thinking that if it's really needed to make the logic complicated. As shown in the commit torvalds/linux@cc31004, it says that the location of tracefs is set to I think we better make the logic simpler as follows.
|
Hi @honggyukim, Thanks for suggesting a better logic. But I did not understand that
But after a few additional searches, I was able to understand the results of qemu rootfs and realized that I didn't know about the relationship between
So I understand why If I will test the unit test code according to the logic you suggested, and finally I will run it in utrace in the local environment. |
That's exactly what I was going to explain. Please send a PR when you're ready. Thanks. |
The commit torvalds/linux@cc31004 says
The author of ftrace and tracefs, Steven Rostedt, mentioned that the location |
The common way to check tracefs is:
|
Hi @namhyung, thanks for suggesting new ideas. Since I don't know about In the corresponding statfs_manpage, the Magic Number for tracefs and debugfs was confirmed as follows.
However, I have a questions.
I like the fact that the logic is a bit simpler. Thank you |
I tried to implement the code using However, no matter how much I looked at the glibc code and the linux kernel code. I couldn't find a field that serves as the f_type of Therefore, the unit test code using
cat tracefs_unit_test2.c
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/vfs.h>
#include <mntent.h>
#define true 1
#define false 0
#define PROC_MOUNTS_PATH "/proc/mounts"
#define TRACEFS_DIR_PATH "/sys/kernel/tracing"
#ifndef TRACEFS_MAGIC
#define TRACEFS_MAGIC 0x74726163
#endif
#define DEBUGFS_DIR_PATH "/sys/kernel/debug/tracing"
#ifndef DEBUGFS_MAGIC
#define DEBUGFS_MAGIC 0x64626720
#endif
char *find_tracing_path(void) {
struct mntent *ent;
char *tracing_dir=NULL;
FILE *fp;
/* open a file with the currently mounted list */
fp = setmntent(PROC_MOUNTS_PATH, "r");
if( fp == NULL ) {
printf("setmntent() return NULL\n");
return NULL;
}
/* compare if "tracefs" or "debugfs" exist in list mounted until EOF(End of File) */
while( NULL != (ent = getmntent(fp)) ) {
if( !strcmp(ent->mnt_fsname, "tracefs") ||
!strcmp(ent->mnt_fsname, "debugfs") )
{
asprintf(&tracing_dir, "%s", ent->mnt_dir);
}
}
/* close mntent fp */
endmntent(fp);
if(tracing_dir != NULL) {
return tracing_dir;
}
return NULL;
}
char *get_tracing_file(const char *name) {
struct statfs fs;
char *tracing_path = NULL;
/* check default tracefs path is mounted */
statfs(TRACEFS_DIR_PATH, &fs);
if( (unsigned long) fs.f_type == TRACEFS_MAGIC ) {
printf("[statfs result] f_type: %#lx\n", (unsigned long) fs.f_type);
asprintf(&tracing_path, "%s", TRACEFS_DIR_PATH);
goto success;
}
/* check default debugfs path is mounted */
statfs(DEBUGFS_DIR_PATH, &fs);
if( (unsigned long) fs.f_type == DEBUGFS_MAGIC ) {
printf("[statfs result] f_type: %#lx\n", (unsigned long) fs.f_type);
asprintf(&tracing_path, "%s", DEBUGFS_DIR_PATH);
goto success;
}
/* last attempt with /proc/mounts */
tracing_path = find_tracing_path();
if( tracing_path != NULL ) {
goto success;
}
return NULL;
success:
asprintf(&tracing_path, "%s/%s", tracing_path, name);
return tracing_path;
}
int main(void){
char *tracing_path = NULL;
tracing_path = get_tracing_file("tracing_on");
if(tracing_path == NULL) {
return 1;
}
printf("\n");
printf("tracing file path : %s\n", tracing_path);
} It can simply be compiled as follows.
The result of running my program is as follows
|
Hmm.. I think this is getting too much complicated unnecessarily. In most cases, the
I think we better make the logic simpler first as above then think about rewriting the fall back routine in a separate PR. |
When parsing /proc/self/mountinfo on some kernels, the number of fields is different and tracefs cannot be obtained. changed methmod to check if paths of "/sys/kernel/tracing (tracefs)" and "/sys/kernel/debug/tracing (debugfs)" exist issues in namhyung#1753 Signed-off-by: gichoelchoi <gichoel0295@gmail.com>
When parsing /proc/self/mountinfo on some kernels, the number of fields is different and tracefs cannot be obtained. changed methmod to check if paths of "/sys/kernel/tracing (tracefs)" and "/sys/kernel/debug/tracing (debugfs)" exist Fixed: namhyung#1753 Signed-off-by: gichoelchoi <gichoel0295@gmail.com>
When parsing /proc/self/mountinfo on some kernels, the number of fields is different and tracefs cannot be obtained. changed methmod to check if paths of "/sys/kernel/tracing (tracefs)" and "/sys/kernel/debug (debugfs)" exist Fixed: namhyung#1753 Signed-off-by: gichoelchoi <gichoel0295@gmail.com>
When parsing /proc/self/mountinfo on some kernels, the number of fields is different and tracefs cannot be obtained. changed methmod to check if paths of "/sys/kernel/tracing (tracefs)" and "/sys/kernel/debug (debugfs)" exist Fixed: namhyung#1753 Signed-off-by: gichoelchoi <gichoel0295@gmail.com>
Resolve an issue when tracefs path could not be found on some kernels. Fixed: namhyung#1753 Signed-off-by: gichoelchoi <gichoel0295@gmail.com>
This logic change is to address issue namhyung#1753, which was causing issue on some kernels. The previous logic used '/proc/self/mountinfo', but in some cases the number of fields was different, causing a parse error. This has been fixed by using getmntent() and setmntent() to parse '/proc/mounts' structurally. Signed-off-by: Gichoel Choi <gichoel3101@gmail.com>
This logic change is to address issue namhyung#1753, which was causing issue on some kernels. The previous logic used '/proc/self/mountinfo', but in some cases the number of fields was different, causing a parse error. This has been fixed by using getmntent() and setmntent() to parse '/proc/mounts' structurally. Signed-off-by: Gichoel Choi <gichoel3101@gmail.com>
The current way of finding tracefs for kernel tracing was implemented in #1476.
It assumes that
/proc/<pid>/mountinfo
looks as follows.So it detects the file system type from the
/proc/self/mountinfo
. For example, the following input can be properly parsed and successfully findsmount_point
andfs_type
as written infind_tracing_dir
.However, it fails detecting
fs_type
from the following my qemu rootfs and it makes kernel tracing disabled. The following line has one less word as shown asshared:18
in the above example.As I mentioned at #1471 (comment), I think we should use
getmntent
to find the mount point.The text was updated successfully, but these errors were encountered: