xref: /aosp_15_r20/external/bcc/libbpf-tools/readahead.bpf.c (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2020 Wenbo Zhang
3 #include <vmlinux.h>
4 #include <bpf/bpf_helpers.h>
5 #include <bpf/bpf_tracing.h>
6 #include "readahead.h"
7 #include "bits.bpf.h"
8 
9 #define MAX_ENTRIES	10240
10 
11 struct {
12 	__uint(type, BPF_MAP_TYPE_HASH);
13 	__uint(max_entries, MAX_ENTRIES);
14 	__type(key, u32);
15 	__type(value, u64);
16 } in_readahead SEC(".maps");
17 
18 struct {
19 	__uint(type, BPF_MAP_TYPE_HASH);
20 	__uint(max_entries, MAX_ENTRIES);
21 	__type(key, struct page *);
22 	__type(value, u64);
23 } birth SEC(".maps");
24 
25 struct hist hist = {};
26 
27 SEC("fentry/do_page_cache_ra")
BPF_PROG(do_page_cache_ra)28 int BPF_PROG(do_page_cache_ra)
29 {
30 	u32 pid = bpf_get_current_pid_tgid();
31 	u64 one = 1;
32 
33 	bpf_map_update_elem(&in_readahead, &pid, &one, 0);
34 	return 0;
35 }
36 
37 SEC("fexit/__page_cache_alloc")
BPF_PROG(page_cache_alloc_ret,gfp_t gfp,struct page * ret)38 int BPF_PROG(page_cache_alloc_ret, gfp_t gfp, struct page *ret)
39 {
40 	u32 pid = bpf_get_current_pid_tgid();
41 	u64 ts;
42 
43 	if (!bpf_map_lookup_elem(&in_readahead, &pid))
44 		return 0;
45 
46 	ts = bpf_ktime_get_ns();
47 	bpf_map_update_elem(&birth, &ret, &ts, 0);
48 	__sync_fetch_and_add(&hist.unused, 1);
49 	__sync_fetch_and_add(&hist.total, 1);
50 
51 	return 0;
52 }
53 
54 SEC("fexit/do_page_cache_ra")
BPF_PROG(do_page_cache_ra_ret)55 int BPF_PROG(do_page_cache_ra_ret)
56 {
57 	u32 pid = bpf_get_current_pid_tgid();
58 
59 	bpf_map_delete_elem(&in_readahead, &pid);
60 	return 0;
61 }
62 
63 SEC("fentry/mark_page_accessed")
BPF_PROG(mark_page_accessed,struct page * page)64 int BPF_PROG(mark_page_accessed, struct page *page)
65 {
66 	u64 *tsp, slot, ts = bpf_ktime_get_ns();
67 	s64 delta;
68 
69 	tsp = bpf_map_lookup_elem(&birth, &page);
70 	if (!tsp)
71 		return 0;
72 	delta = (s64)(ts - *tsp);
73 	if (delta < 0)
74 		goto update_and_cleanup;
75 	slot = log2l(delta / 1000000U);
76 	if (slot >= MAX_SLOTS)
77 		slot = MAX_SLOTS - 1;
78 	__sync_fetch_and_add(&hist.slots[slot], 1);
79 
80 update_and_cleanup:
81 	__sync_fetch_and_add(&hist.unused, -1);
82 	bpf_map_delete_elem(&birth, &page);
83 
84 	return 0;
85 }
86 
87 char LICENSE[] SEC("license") = "GPL";
88