1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/python 2*387f9dfdSAndroid Build Coastguard Worker# @lint-avoid-python-3-compatibility-imports 3*387f9dfdSAndroid Build Coastguard Worker# 4*387f9dfdSAndroid Build Coastguard Worker# filelife Trace the lifespan of short-lived files. 5*387f9dfdSAndroid Build Coastguard Worker# For Linux, uses BCC, eBPF. Embedded C. 6*387f9dfdSAndroid Build Coastguard Worker# 7*387f9dfdSAndroid Build Coastguard Worker# This traces the creation and deletion of files, providing information 8*387f9dfdSAndroid Build Coastguard Worker# on who deleted the file, the file age, and the file name. The intent is to 9*387f9dfdSAndroid Build Coastguard Worker# provide information on short-lived files, for debugging or performance 10*387f9dfdSAndroid Build Coastguard Worker# analysis. 11*387f9dfdSAndroid Build Coastguard Worker# 12*387f9dfdSAndroid Build Coastguard Worker# USAGE: filelife [-h] [-p PID] 13*387f9dfdSAndroid Build Coastguard Worker# 14*387f9dfdSAndroid Build Coastguard Worker# Copyright 2016 Netflix, Inc. 15*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License") 16*387f9dfdSAndroid Build Coastguard Worker# 17*387f9dfdSAndroid Build Coastguard Worker# 08-Feb-2015 Brendan Gregg Created this. 18*387f9dfdSAndroid Build Coastguard Worker 19*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function 20*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF 21*387f9dfdSAndroid Build Coastguard Workerimport argparse 22*387f9dfdSAndroid Build Coastguard Workerfrom time import strftime 23*387f9dfdSAndroid Build Coastguard Worker 24*387f9dfdSAndroid Build Coastguard Worker# arguments 25*387f9dfdSAndroid Build Coastguard Workerexamples = """examples: 26*387f9dfdSAndroid Build Coastguard Worker ./filelife # trace all stat() syscalls 27*387f9dfdSAndroid Build Coastguard Worker ./filelife -p 181 # only trace PID 181 28*387f9dfdSAndroid Build Coastguard Worker""" 29*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser( 30*387f9dfdSAndroid Build Coastguard Worker description="Trace stat() syscalls", 31*387f9dfdSAndroid Build Coastguard Worker formatter_class=argparse.RawDescriptionHelpFormatter, 32*387f9dfdSAndroid Build Coastguard Worker epilog=examples) 33*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-p", "--pid", 34*387f9dfdSAndroid Build Coastguard Worker help="trace this PID only") 35*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args() 36*387f9dfdSAndroid Build Coastguard Workerdebug = 0 37*387f9dfdSAndroid Build Coastguard Worker 38*387f9dfdSAndroid Build Coastguard Worker# define BPF program 39*387f9dfdSAndroid Build Coastguard Workerbpf_text = """ 40*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h> 41*387f9dfdSAndroid Build Coastguard Worker#include <linux/fs.h> 42*387f9dfdSAndroid Build Coastguard Worker 43*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(birth, struct dentry *); 44*387f9dfdSAndroid Build Coastguard Worker 45*387f9dfdSAndroid Build Coastguard Worker// trace file creation time 46*387f9dfdSAndroid Build Coastguard Workerint trace_create(struct pt_regs *ctx, struct inode *dir, struct dentry *dentry) 47*387f9dfdSAndroid Build Coastguard Worker{ 48*387f9dfdSAndroid Build Coastguard Worker u32 pid = bpf_get_current_pid_tgid(); 49*387f9dfdSAndroid Build Coastguard Worker FILTER 50*387f9dfdSAndroid Build Coastguard Worker 51*387f9dfdSAndroid Build Coastguard Worker u64 ts = bpf_ktime_get_ns(); 52*387f9dfdSAndroid Build Coastguard Worker birth.update(&dentry, &ts); 53*387f9dfdSAndroid Build Coastguard Worker 54*387f9dfdSAndroid Build Coastguard Worker return 0; 55*387f9dfdSAndroid Build Coastguard Worker}; 56*387f9dfdSAndroid Build Coastguard Worker 57*387f9dfdSAndroid Build Coastguard Worker// trace file deletion and output details 58*387f9dfdSAndroid Build Coastguard Workerint trace_unlink(struct pt_regs *ctx, struct inode *dir, struct dentry *dentry) 59*387f9dfdSAndroid Build Coastguard Worker{ 60*387f9dfdSAndroid Build Coastguard Worker u32 pid = bpf_get_current_pid_tgid(); 61*387f9dfdSAndroid Build Coastguard Worker FILTER 62*387f9dfdSAndroid Build Coastguard Worker 63*387f9dfdSAndroid Build Coastguard Worker u64 *tsp, delta; 64*387f9dfdSAndroid Build Coastguard Worker tsp = birth.lookup(&dentry); 65*387f9dfdSAndroid Build Coastguard Worker if (tsp == 0) { 66*387f9dfdSAndroid Build Coastguard Worker return 0; // missed create 67*387f9dfdSAndroid Build Coastguard Worker } 68*387f9dfdSAndroid Build Coastguard Worker delta = (bpf_ktime_get_ns() - *tsp) / 1000000; 69*387f9dfdSAndroid Build Coastguard Worker birth.delete(&dentry); 70*387f9dfdSAndroid Build Coastguard Worker 71*387f9dfdSAndroid Build Coastguard Worker if (dentry->d_iname[0] == 0) 72*387f9dfdSAndroid Build Coastguard Worker return 0; 73*387f9dfdSAndroid Build Coastguard Worker 74*387f9dfdSAndroid Build Coastguard Worker bpf_trace_printk("%d %s\\n", delta, dentry->d_iname); 75*387f9dfdSAndroid Build Coastguard Worker 76*387f9dfdSAndroid Build Coastguard Worker return 0; 77*387f9dfdSAndroid Build Coastguard Worker} 78*387f9dfdSAndroid Build Coastguard Worker""" 79*387f9dfdSAndroid Build Coastguard Workerif args.pid: 80*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('FILTER', 81*387f9dfdSAndroid Build Coastguard Worker 'if (pid != %s) { return 0; }' % args.pid) 82*387f9dfdSAndroid Build Coastguard Workerelse: 83*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('FILTER', '') 84*387f9dfdSAndroid Build Coastguard Workerif debug: 85*387f9dfdSAndroid Build Coastguard Worker print(bpf_text) 86*387f9dfdSAndroid Build Coastguard Worker 87*387f9dfdSAndroid Build Coastguard Worker# initialize BPF 88*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text) 89*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event="vfs_create", fn_name="trace_create") 90*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event="vfs_unlink", fn_name="trace_unlink") 91*387f9dfdSAndroid Build Coastguard Worker 92*387f9dfdSAndroid Build Coastguard Worker# header 93*387f9dfdSAndroid Build Coastguard Workerprint("%-8s %-6s %-16s %-7s %s" % ("TIME", "PID", "COMM", "AGE(s)", "FILE")) 94*387f9dfdSAndroid Build Coastguard Worker 95*387f9dfdSAndroid Build Coastguard Workerstart_ts = 0 96*387f9dfdSAndroid Build Coastguard Worker 97*387f9dfdSAndroid Build Coastguard Worker# format output 98*387f9dfdSAndroid Build Coastguard Workerwhile 1: 99*387f9dfdSAndroid Build Coastguard Worker (task, pid, cpu, flags, ts, msg) = b.trace_fields() 100*387f9dfdSAndroid Build Coastguard Worker (delta, filename) = msg.split(" ", 1) 101*387f9dfdSAndroid Build Coastguard Worker 102*387f9dfdSAndroid Build Coastguard Worker # print columns 103*387f9dfdSAndroid Build Coastguard Worker print("%-8s %-6d %-16s %-7.2f %s" % (strftime("%H:%M:%S"), pid, task, 104*387f9dfdSAndroid Build Coastguard Worker float(delta) / 1000, filename)) 105