• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 	__uint(map_flags, BPF_F_NO_PREALLOC);
17 } in_readahead SEC(".maps");
18 
19 struct {
20 	__uint(type, BPF_MAP_TYPE_HASH);
21 	__uint(max_entries, MAX_ENTRIES);
22 	__type(key, struct page *);
23 	__type(value, u64);
24 	__uint(map_flags, BPF_F_NO_PREALLOC);
25 } birth SEC(".maps");
26 
27 struct hist hist = {};
28 
29 SEC("fentry/do_page_cache_ra")
BPF_PROG(do_page_cache_ra)30 int BPF_PROG(do_page_cache_ra)
31 {
32 	u32 pid = bpf_get_current_pid_tgid();
33 	u64 one = 1;
34 
35 	bpf_map_update_elem(&in_readahead, &pid, &one, 0);
36 	return 0;
37 }
38 
39 SEC("fexit/__page_cache_alloc")
BPF_PROG(page_cache_alloc_ret,gfp_t gfp,struct page * ret)40 int BPF_PROG(page_cache_alloc_ret, gfp_t gfp, struct page *ret)
41 {
42 	u32 pid = bpf_get_current_pid_tgid();
43 	u64 ts;
44 
45 	if (!bpf_map_lookup_elem(&in_readahead, &pid))
46 		return 0;
47 
48 	ts = bpf_ktime_get_ns();
49 	bpf_map_update_elem(&birth, &ret, &ts, 0);
50 	__sync_fetch_and_add(&hist.unused, 1);
51 	__sync_fetch_and_add(&hist.total, 1);
52 
53 	return 0;
54 }
55 
56 SEC("fexit/do_page_cache_ra")
BPF_PROG(do_page_cache_ra_ret)57 int BPF_PROG(do_page_cache_ra_ret)
58 {
59 	u32 pid = bpf_get_current_pid_tgid();
60 
61 	bpf_map_delete_elem(&in_readahead, &pid);
62 	return 0;
63 }
64 
65 SEC("fentry/mark_page_accessed")
BPF_PROG(mark_page_accessed,struct page * page)66 int BPF_PROG(mark_page_accessed, struct page *page)
67 {
68 	u64 *tsp, slot, ts = bpf_ktime_get_ns();
69 	s64 delta;
70 
71 	tsp = bpf_map_lookup_elem(&birth, &page);
72 	if (!tsp)
73 		return 0;
74 	delta = (s64)(ts - *tsp);
75 	if (delta < 0)
76 		goto update_and_cleanup;
77 	slot = log2l(delta / 1000000U);
78 	if (slot >= MAX_SLOTS)
79 		slot = MAX_SLOTS - 1;
80 	__sync_fetch_and_add(&hist.slots[slot], 1);
81 
82 update_and_cleanup:
83 	__sync_fetch_and_add(&hist.unused, -1);
84 	bpf_map_delete_elem(&birth, &page);
85 
86 	return 0;
87 }
88 
89 char LICENSE[] SEC("license") = "GPL";
90