Skip to content
This repository was archived by the owner on Jul 16, 2020. It is now read-only.

Commit f768410

Browse files
Joel Fernandesppajda
authored andcommitted
ANDROID: Add a tracepoint for mapping inode to full path
This will be used by eBPF and the iorapd project for high speed inode/dev numbers to file path lookup. Look at the inodemap CL for more details about of eBPF and iorapd using the tracepoint. This is planned to be used by the inodemap BPF program. Also, ART folks have been using this tracepoint for debugging "unknown inode numer" issues. The tracepoint will be out of tree, and not sent upstream, since VFS developers don't accept tracepoints strictly. Test: Run "find /" command in emulator and measure completion time with/without treacepoint. find does a flood of lookups which stresses the tracepoint. No performance change observed. Test: eBPF prototypes (wip) successfully read data from the tracepoint. OOT Bug: 139663736 Bug: 135143784 Bug: 137393447 Change-Id: I657f374659673a9c8853530d73c0622dbdbab146 Signed-off-by: Joel Fernandes <joelaf@google.com> (cherry picked from commit 987732fcbbe3ea78368c28e5a0d0d236be61420f) (cherry picked from commit 2104283a8d7349011860d9bffb8a3d25456e6d20) (cherry picked from commit 4bfd158)
1 parent 8a4a2db commit f768410

2 files changed

Lines changed: 129 additions & 3 deletions

File tree

fs/namei.c

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@
4040
#include "internal.h"
4141
#include "mount.h"
4242

43+
#define CREATE_TRACE_POINTS
44+
#include <trace/events/namei.h>
45+
4346
/* [Feb-1997 T. Schoebel-Theuer]
4447
* Fundamental changes in the pathname lookup mechanisms (namei)
4548
* were necessary because of omirr. The reason is that omirr needs
@@ -621,6 +624,81 @@ static inline int d_revalidate(struct dentry *dentry, unsigned int flags)
621624
return dentry->d_op->d_revalidate(dentry, flags);
622625
}
623626

627+
#define INIT_PATH_SIZE 64
628+
629+
static void success_walk_trace(struct nameidata *nd)
630+
{
631+
struct path *pt = &nd->path;
632+
struct inode *i = nd->inode;
633+
char buf[INIT_PATH_SIZE], *try_buf;
634+
int cur_path_size;
635+
char *p;
636+
637+
/* When eBPF/ tracepoint is disabled, keep overhead low. */
638+
if (!trace_inodepath_enabled())
639+
return;
640+
641+
/* First try stack allocated buffer. */
642+
try_buf = buf;
643+
cur_path_size = INIT_PATH_SIZE;
644+
645+
while (cur_path_size <= PATH_MAX) {
646+
/* Free previous heap allocation if we are now trying
647+
* a second or later heap allocation.
648+
*/
649+
if (try_buf != buf)
650+
kfree(try_buf);
651+
652+
/* All but the first alloc are on the heap. */
653+
if (cur_path_size != INIT_PATH_SIZE) {
654+
try_buf = kmalloc(cur_path_size, GFP_KERNEL);
655+
if (!try_buf) {
656+
try_buf = buf;
657+
sprintf(try_buf, "error:buf_alloc_failed");
658+
break;
659+
}
660+
}
661+
662+
p = d_path(pt, try_buf, cur_path_size);
663+
664+
if (!IS_ERR(p)) {
665+
char *end = mangle_path(try_buf, p, "\n");
666+
667+
if (end) {
668+
try_buf[end - try_buf] = 0;
669+
break;
670+
} else {
671+
/* On mangle errors, double path size
672+
* till PATH_MAX.
673+
*/
674+
cur_path_size = cur_path_size << 1;
675+
continue;
676+
}
677+
}
678+
679+
if (PTR_ERR(p) == -ENAMETOOLONG) {
680+
/* If d_path complains that name is too long,
681+
* then double path size till PATH_MAX.
682+
*/
683+
cur_path_size = cur_path_size << 1;
684+
continue;
685+
}
686+
687+
sprintf(try_buf, "error:d_path_failed_%lu",
688+
-1 * PTR_ERR(p));
689+
break;
690+
}
691+
692+
if (cur_path_size > PATH_MAX)
693+
sprintf(try_buf, "error:d_path_name_too_long");
694+
695+
trace_inodepath(i, try_buf);
696+
697+
if (try_buf != buf)
698+
kfree(try_buf);
699+
return;
700+
}
701+
624702
/**
625703
* complete_walk - successful completion of path walk
626704
* @nd: pointer nameidata
@@ -659,15 +737,21 @@ static int complete_walk(struct nameidata *nd)
659737
rcu_read_unlock();
660738
}
661739

662-
if (likely(!(nd->flags & LOOKUP_JUMPED)))
740+
if (likely(!(nd->flags & LOOKUP_JUMPED))) {
741+
success_walk_trace(nd);
663742
return 0;
743+
}
664744

665-
if (likely(!(dentry->d_flags & DCACHE_OP_WEAK_REVALIDATE)))
745+
if (likely(!(dentry->d_flags & DCACHE_OP_WEAK_REVALIDATE))) {
746+
success_walk_trace(nd);
666747
return 0;
748+
}
667749

668750
status = dentry->d_op->d_weak_revalidate(dentry, nd->flags);
669-
if (status > 0)
751+
if (status > 0) {
752+
success_walk_trace(nd);
670753
return 0;
754+
}
671755

672756
if (!status)
673757
status = -ESTALE;

include/trace/events/namei.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#undef TRACE_SYSTEM
3+
#define TRACE_SYSTEM namei
4+
5+
#if !defined(_TRACE_INODEPATH_H) || defined(TRACE_HEADER_MULTI_READ)
6+
#define _TRACE_INODEPATH_H
7+
8+
#include <linux/types.h>
9+
#include <linux/tracepoint.h>
10+
#include <linux/mm.h>
11+
#include <linux/memcontrol.h>
12+
#include <linux/device.h>
13+
#include <linux/kdev_t.h>
14+
15+
TRACE_EVENT(inodepath,
16+
TP_PROTO(struct inode *inode, char *path),
17+
18+
TP_ARGS(inode, path),
19+
20+
TP_STRUCT__entry(
21+
/* dev_t and ino_t are arch dependent bit width
22+
* so just use 64-bit
23+
*/
24+
__field(unsigned long, ino)
25+
__field(unsigned long, dev)
26+
__string(path, path)
27+
),
28+
29+
TP_fast_assign(
30+
__entry->ino = inode->i_ino;
31+
__entry->dev = inode->i_sb->s_dev;
32+
__assign_str(path, path);
33+
),
34+
35+
TP_printk("dev %d:%d ino=%lu path=%s",
36+
MAJOR(__entry->dev), MINOR(__entry->dev),
37+
__entry->ino, __get_str(path))
38+
);
39+
#endif /* _TRACE_INODEPATH_H */
40+
41+
/* This part must be outside protection */
42+
#include <trace/define_trace.h>

0 commit comments

Comments
 (0)