0bf9805dfd
[ Upstream commit c6fddb28bad26e5472cb7acf7b04cd5126f1a4ab ] The xxx_mountpoint() interface provided by fs.c finds mount points for common pseudo filesystems. The first time xxx_mountpoint() is invoked, it scans the mount table (/proc/mounts) looking for a match. If found, it is cached. The price to scan /proc/mounts is paid once if the mount is found. When the mount point is not found, subsequent calls to xxx_mountpoint() scan /proc/mounts over and over again. There is no caching. This causes a scaling issue in perf record with hugeltbfs__mountpoint(). The function is called for each process found in synthesize__mmap_events(). If the machine has thousands of processes and if the /proc/mounts has many entries this could cause major overhead in perf record. We have observed multi-second slowdowns on some configurations. As an example on a laptop: Before: $ sudo umount /dev/hugepages $ strace -e trace=openat -o /tmp/tt perf record -a ls $ fgrep mounts /tmp/tt 285 After: $ sudo umount /dev/hugepages $ strace -e trace=openat -o /tmp/tt perf record -a ls $ fgrep mounts /tmp/tt 1 One could argue that the non-caching in case the moint point is not found is intentional. That way subsequent calls may discover a moint point if the sysadmin mounts the filesystem. But the same argument could be made against caching the mount point. It could be unmounted causing errors. It all depends on the intent of the interface. This patch assumes it is expected to scan /proc/mounts once. The patch documents the caching behavior in the fs.h header file. An alternative would be to just fix perf record. But it would solve the problem with hugetlbs__mountpoint() but there could be similar issues (possibly down the line) with other xxx_mountpoint() calls in perf or other tools. Signed-off-by: Stephane Eranian <eranian@google.com> Reviewed-by: Ian Rogers <irogers@google.com> Acked-by: Jiri Olsa <jolsa@redhat.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andrey Zhizhikin <andrey.z@gmail.com> Cc: Kan Liang <kan.liang@linux.intel.com> Cc: Kefeng Wang <wangkefeng.wang@huawei.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Petr Mladek <pmladek@suse.com> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lore.kernel.org/lkml/20200402154357.107873-3-irogers@google.com Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
61 lines
1.7 KiB
C
61 lines
1.7 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef __API_FS__
|
|
#define __API_FS__
|
|
|
|
#include <stdbool.h>
|
|
#include <unistd.h>
|
|
|
|
/*
|
|
* On most systems <limits.h> would have given us this, but not on some systems
|
|
* (e.g. GNU/Hurd).
|
|
*/
|
|
#ifndef PATH_MAX
|
|
#define PATH_MAX 4096
|
|
#endif
|
|
|
|
#define FS(name) \
|
|
const char *name##__mountpoint(void); \
|
|
const char *name##__mount(void); \
|
|
bool name##__configured(void); \
|
|
|
|
/*
|
|
* The xxxx__mountpoint() entry points find the first match mount point for each
|
|
* filesystems listed below, where xxxx is the filesystem type.
|
|
*
|
|
* The interface is as follows:
|
|
*
|
|
* - If a mount point is found on first call, it is cached and used for all
|
|
* subsequent calls.
|
|
*
|
|
* - If a mount point is not found, NULL is returned on first call and all
|
|
* subsequent calls.
|
|
*/
|
|
FS(sysfs)
|
|
FS(procfs)
|
|
FS(debugfs)
|
|
FS(tracefs)
|
|
FS(hugetlbfs)
|
|
FS(bpf_fs)
|
|
|
|
#undef FS
|
|
|
|
|
|
int filename__read_int(const char *filename, int *value);
|
|
int filename__read_ull(const char *filename, unsigned long long *value);
|
|
int filename__read_xll(const char *filename, unsigned long long *value);
|
|
int filename__read_str(const char *filename, char **buf, size_t *sizep);
|
|
|
|
int filename__write_int(const char *filename, int value);
|
|
|
|
int procfs__read_str(const char *entry, char **buf, size_t *sizep);
|
|
|
|
int sysctl__read_int(const char *sysctl, int *value);
|
|
int sysfs__read_int(const char *entry, int *value);
|
|
int sysfs__read_ull(const char *entry, unsigned long long *value);
|
|
int sysfs__read_xll(const char *entry, unsigned long long *value);
|
|
int sysfs__read_str(const char *entry, char **buf, size_t *sizep);
|
|
int sysfs__read_bool(const char *entry, bool *value);
|
|
|
|
int sysfs__write_int(const char *entry, int value);
|
|
#endif /* __API_FS__ */
|