fs: add backtrace to where file opens
Signed-off-by: Xu Xingliang <xuxingliang@xiaomi.com>
This commit is contained in:
parent
add8b71fee
commit
69d8a17dda
|
@ -49,6 +49,7 @@ CONFIG_FRAME_POINTER=y
|
||||||
CONFIG_FSUTILS_PASSWD=y
|
CONFIG_FSUTILS_PASSWD=y
|
||||||
CONFIG_FSUTILS_PASSWD_READONLY=y
|
CONFIG_FSUTILS_PASSWD_READONLY=y
|
||||||
CONFIG_FS_AIO=y
|
CONFIG_FS_AIO=y
|
||||||
|
CONFIG_FS_BACKTRACE=8
|
||||||
CONFIG_FS_BINFS=y
|
CONFIG_FS_BINFS=y
|
||||||
CONFIG_FS_FAT=y
|
CONFIG_FS_FAT=y
|
||||||
CONFIG_FS_HOSTFS=y
|
CONFIG_FS_HOSTFS=y
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <nuttx/fs/fs.h>
|
#include <nuttx/fs/fs.h>
|
||||||
#include <nuttx/kmalloc.h>
|
#include <nuttx/kmalloc.h>
|
||||||
|
@ -460,6 +461,8 @@ found:
|
||||||
inode_addref(inode);
|
inode_addref(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FS_ADD_BACKTRACE(filep);
|
||||||
|
|
||||||
#ifdef CONFIG_FDCHECK
|
#ifdef CONFIG_FDCHECK
|
||||||
return fdcheck_protect(i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j);
|
return fdcheck_protect(i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j);
|
||||||
#else
|
#else
|
||||||
|
@ -487,6 +490,27 @@ int file_allocate(FAR struct inode *inode, int oflags, off_t pos,
|
||||||
pos, priv, minfd, addref);
|
pos, priv, minfd, addref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FAR char *file_dump_backtrace(FAR struct file *filep, FAR char *buffer,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
#if CONFIG_FS_BACKTRACE > 0
|
||||||
|
FAR const char *format = "%0*p ";
|
||||||
|
int k;
|
||||||
|
|
||||||
|
buffer[0] = '\0';
|
||||||
|
for (k = 0; k < CONFIG_FS_BACKTRACE && filep->f_backtrace[k]; k++)
|
||||||
|
{
|
||||||
|
snprintf(buffer + k * FS_BACKTRACE_WIDTH,
|
||||||
|
len - k * FS_BACKTRACE_WIDTH,
|
||||||
|
format, FS_BACKTRACE_WIDTH - 1,
|
||||||
|
filep->f_backtrace[k]);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
buffer[0] = '\0';
|
||||||
|
#endif
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: files_duplist
|
* Name: files_duplist
|
||||||
*
|
*
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <sched.h>
|
||||||
|
|
||||||
#include <nuttx/kmalloc.h>
|
#include <nuttx/kmalloc.h>
|
||||||
#include <nuttx/fs/fs.h>
|
#include <nuttx/fs/fs.h>
|
||||||
|
@ -65,6 +66,23 @@
|
||||||
} \
|
} \
|
||||||
while (0)
|
while (0)
|
||||||
|
|
||||||
|
#if CONFIG_FS_BACKTRACE > 0
|
||||||
|
# define FS_ADD_BACKTRACE(filep) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
int n = sched_backtrace(_SCHED_GETTID(), filep->f_backtrace, \
|
||||||
|
CONFIG_FS_BACKTRACE, \
|
||||||
|
CONFIG_FS_BACKTRACE_SKIP); \
|
||||||
|
if (n < CONFIG_FS_BACKTRACE) \
|
||||||
|
{ \
|
||||||
|
(filep->f_backtrace)[n] = NULL; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
#else
|
||||||
|
# define FS_ADD_BACKTRACE(filep)
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Types
|
* Public Types
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
|
@ -1244,8 +1244,6 @@ static ssize_t proc_groupfd(FAR struct proc_file_s *procfile,
|
||||||
size_t buflen, off_t offset)
|
size_t buflen, off_t offset)
|
||||||
{
|
{
|
||||||
FAR struct task_group_s *group = tcb->group;
|
FAR struct task_group_s *group = tcb->group;
|
||||||
FAR struct file *filep;
|
|
||||||
char path[PATH_MAX];
|
|
||||||
size_t remaining;
|
size_t remaining;
|
||||||
size_t linesize;
|
size_t linesize;
|
||||||
size_t copysize;
|
size_t copysize;
|
||||||
|
@ -1253,6 +1251,10 @@ static ssize_t proc_groupfd(FAR struct proc_file_s *procfile,
|
||||||
int count;
|
int count;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
FAR struct file *filep;
|
||||||
|
char path[PATH_MAX];
|
||||||
|
char backtrace[FS_BACKTRACE_BUFFER_LEN];
|
||||||
|
|
||||||
DEBUGASSERT(group != NULL);
|
DEBUGASSERT(group != NULL);
|
||||||
|
|
||||||
count = files_countlist(&group->tg_filelist);
|
count = files_countlist(&group->tg_filelist);
|
||||||
|
@ -1265,8 +1267,14 @@ static ssize_t proc_groupfd(FAR struct proc_file_s *procfile,
|
||||||
totalsize = 0;
|
totalsize = 0;
|
||||||
|
|
||||||
linesize = procfs_snprintf(procfile->line, STATUS_LINELEN,
|
linesize = procfs_snprintf(procfile->line, STATUS_LINELEN,
|
||||||
"\n%-3s %-7s %-4s %-9s %s\n",
|
"\n%-3s %-7s %-4s %-9s %-14s %s\n",
|
||||||
"FD", "OFLAGS", "TYPE", "POS", "PATH");
|
"FD", "OFLAGS", "TYPE", "POS", "PATH",
|
||||||
|
#if CONFIG_FS_BACKTRACE > 0
|
||||||
|
"BACKTRACE"
|
||||||
|
#else
|
||||||
|
""
|
||||||
|
#endif
|
||||||
|
);
|
||||||
copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining,
|
copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining,
|
||||||
&offset);
|
&offset);
|
||||||
|
|
||||||
|
@ -1298,12 +1306,22 @@ static ssize_t proc_groupfd(FAR struct proc_file_s *procfile,
|
||||||
}
|
}
|
||||||
|
|
||||||
linesize = procfs_snprintf(procfile->line, STATUS_LINELEN,
|
linesize = procfs_snprintf(procfile->line, STATUS_LINELEN,
|
||||||
"%-3d %-7d %-4x %-9ld %s\n",
|
"%-3d %-7d %-4x %-9ld %-14s %s\n",
|
||||||
i, filep->f_oflags,
|
i, filep->f_oflags,
|
||||||
INODE_GET_TYPE(filep->f_inode),
|
INODE_GET_TYPE(filep->f_inode),
|
||||||
(long)filep->f_pos, path);
|
(long)filep->f_pos, path,
|
||||||
|
file_dump_backtrace(filep,
|
||||||
|
backtrace,
|
||||||
|
sizeof(backtrace)
|
||||||
|
)
|
||||||
|
);
|
||||||
copysize = procfs_memcpy(procfile->line, linesize,
|
copysize = procfs_memcpy(procfile->line, linesize,
|
||||||
buffer, remaining, &offset);
|
buffer, remaining, &offset);
|
||||||
|
if (linesize + 1 == STATUS_LINELEN)
|
||||||
|
{
|
||||||
|
procfile->line[STATUS_LINELEN - 2] = '\n';
|
||||||
|
linesize = STATUS_LINELEN;
|
||||||
|
}
|
||||||
|
|
||||||
totalsize += copysize;
|
totalsize += copysize;
|
||||||
buffer += copysize;
|
buffer += copysize;
|
||||||
|
|
|
@ -64,3 +64,16 @@ config SIGNAL_FD_NPOLLWAITERS
|
||||||
Maximum number of threads that can be waiting on poll()
|
Maximum number of threads that can be waiting on poll()
|
||||||
|
|
||||||
endif # SIGNAL_FD
|
endif # SIGNAL_FD
|
||||||
|
|
||||||
|
config FS_BACKTRACE
|
||||||
|
int "VFS backtrace"
|
||||||
|
default 0
|
||||||
|
---help---
|
||||||
|
Add backtrace to vfs file open.
|
||||||
|
|
||||||
|
config FS_BACKTRACE_SKIP
|
||||||
|
int "Backtrace to skip"
|
||||||
|
default 2
|
||||||
|
depends on FS_BACKTRACE > 0
|
||||||
|
---help---
|
||||||
|
Skip depth of backtrace.
|
||||||
|
|
|
@ -174,6 +174,7 @@ int file_dup3(FAR struct file *filep1, FAR struct file *filep2, int flags)
|
||||||
filep2->f_tag_fdcheck = filep1->f_tag_fdcheck;
|
filep2->f_tag_fdcheck = filep1->f_tag_fdcheck;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
FS_ADD_BACKTRACE(filep2);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -164,6 +164,9 @@
|
||||||
#define CH_STAT_ATIME (1 << 3)
|
#define CH_STAT_ATIME (1 << 3)
|
||||||
#define CH_STAT_MTIME (1 << 4)
|
#define CH_STAT_MTIME (1 << 4)
|
||||||
|
|
||||||
|
#define FS_BACKTRACE_WIDTH (sizeof(uintptr_t) * 2 + 3) /* 3: ' 0x' prefix */
|
||||||
|
#define FS_BACKTRACE_BUFFER_LEN (CONFIG_FS_BACKTRACE * FS_BACKTRACE_WIDTH + 1)
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Type Definitions
|
* Public Type Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
@ -475,6 +478,10 @@ struct file
|
||||||
#ifdef CONFIG_FDCHECK
|
#ifdef CONFIG_FDCHECK
|
||||||
uint8_t f_tag_fdcheck; /* File owner fdcheck tag, init to 0 */
|
uint8_t f_tag_fdcheck; /* File owner fdcheck tag, init to 0 */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_FS_BACKTRACE > 0
|
||||||
|
FAR void *f_backtrace[CONFIG_FS_BACKTRACE]; /* Backtrace to while file opens */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This defines a two layer array of files indexed by the file descriptor.
|
/* This defines a two layer array of files indexed by the file descriptor.
|
||||||
|
@ -946,6 +953,20 @@ int file_allocate_from_tcb(FAR struct tcb_s *tcb, FAR struct inode *inode,
|
||||||
int file_allocate(FAR struct inode *inode, int oflags, off_t pos,
|
int file_allocate(FAR struct inode *inode, int oflags, off_t pos,
|
||||||
FAR void *priv, int minfd, bool addref);
|
FAR void *priv, int minfd, bool addref);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: file_dump_backtrace
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Dump the backtrace of the file open to given buffer.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Returns the backtrace string, it could be empty.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
FAR char *file_dump_backtrace(FAR struct file *filep, FAR char *buffer,
|
||||||
|
size_t len);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: file_dup
|
* Name: file_dup
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue