// SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2020 Wenbo Zhang #include #include #include #include "readahead.h" #include "bits.bpf.h" #define MAX_ENTRIES 10240 struct { __uint(type, BPF_MAP_TYPE_HASH); __uint(max_entries, MAX_ENTRIES); __type(key, u32); __type(value, u64); __uint(map_flags, BPF_F_NO_PREALLOC); } in_readahead SEC(".maps"); struct { __uint(type, BPF_MAP_TYPE_HASH); __uint(max_entries, MAX_ENTRIES); __type(key, struct page *); __type(value, u64); __uint(map_flags, BPF_F_NO_PREALLOC); } birth SEC(".maps"); struct hist hist = {}; SEC("fentry/do_page_cache_ra") int BPF_PROG(do_page_cache_ra) { u32 pid = bpf_get_current_pid_tgid(); u64 one = 1; bpf_map_update_elem(&in_readahead, &pid, &one, 0); return 0; } SEC("fexit/__page_cache_alloc") int BPF_PROG(page_cache_alloc_ret, gfp_t gfp, struct page *ret) { u32 pid = bpf_get_current_pid_tgid(); u64 ts; if (!bpf_map_lookup_elem(&in_readahead, &pid)) return 0; ts = bpf_ktime_get_ns(); bpf_map_update_elem(&birth, &ret, &ts, 0); __sync_fetch_and_add(&hist.unused, 1); __sync_fetch_and_add(&hist.total, 1); return 0; } SEC("fexit/do_page_cache_ra") int BPF_PROG(do_page_cache_ra_ret) { u32 pid = bpf_get_current_pid_tgid(); bpf_map_delete_elem(&in_readahead, &pid); return 0; } SEC("fentry/mark_page_accessed") int BPF_PROG(mark_page_accessed, struct page *page) { u64 *tsp, slot, ts = bpf_ktime_get_ns(); s64 delta; tsp = bpf_map_lookup_elem(&birth, &page); if (!tsp) return 0; delta = (s64)(ts - *tsp); if (delta < 0) goto update_and_cleanup; slot = log2l(delta / 1000000U); if (slot >= MAX_SLOTS) slot = MAX_SLOTS - 1; __sync_fetch_and_add(&hist.slots[slot], 1); update_and_cleanup: __sync_fetch_and_add(&hist.unused, -1); bpf_map_delete_elem(&birth, &page); return 0; } char LICENSE[] SEC("license") = "GPL";