1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env python 2*387f9dfdSAndroid Build Coastguard Worker# @lint-avoid-python-3-compatibility-imports 3*387f9dfdSAndroid Build Coastguard Worker# 4*387f9dfdSAndroid Build Coastguard Worker# mdflush Trace md flush events. 5*387f9dfdSAndroid Build Coastguard Worker# For Linux, uses BCC, eBPF. 6*387f9dfdSAndroid Build Coastguard Worker# 7*387f9dfdSAndroid Build Coastguard Worker# Todo: add more details of the flush (latency, I/O count). 8*387f9dfdSAndroid Build Coastguard Worker# 9*387f9dfdSAndroid Build Coastguard Worker# Copyright 2016 Netflix, Inc. 10*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License") 11*387f9dfdSAndroid Build Coastguard Worker# 12*387f9dfdSAndroid Build Coastguard Worker# 13-Feb-2015 Brendan Gregg Created this. 13*387f9dfdSAndroid Build Coastguard Worker 14*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function 15*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF 16*387f9dfdSAndroid Build Coastguard Workerfrom time import strftime 17*387f9dfdSAndroid Build Coastguard Worker 18*387f9dfdSAndroid Build Coastguard Worker# define BPF program 19*387f9dfdSAndroid Build Coastguard Workerbpf_text=""" 20*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h> 21*387f9dfdSAndroid Build Coastguard Worker#include <linux/sched.h> 22*387f9dfdSAndroid Build Coastguard Worker#include <linux/blkdev.h> 23*387f9dfdSAndroid Build Coastguard Worker#include <linux/bio.h> 24*387f9dfdSAndroid Build Coastguard Worker 25*387f9dfdSAndroid Build Coastguard Workerstruct data_t { 26*387f9dfdSAndroid Build Coastguard Worker u32 pid; 27*387f9dfdSAndroid Build Coastguard Worker char comm[TASK_COMM_LEN]; 28*387f9dfdSAndroid Build Coastguard Worker char disk[DISK_NAME_LEN]; 29*387f9dfdSAndroid Build Coastguard Worker}; 30*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(events); 31*387f9dfdSAndroid Build Coastguard Worker 32*387f9dfdSAndroid Build Coastguard Workerint kprobe__md_flush_request(struct pt_regs *ctx, void *mddev, struct bio *bio) 33*387f9dfdSAndroid Build Coastguard Worker{ 34*387f9dfdSAndroid Build Coastguard Worker struct data_t data = {}; 35*387f9dfdSAndroid Build Coastguard Worker data.pid = bpf_get_current_pid_tgid() >> 32; 36*387f9dfdSAndroid Build Coastguard Worker bpf_get_current_comm(&data.comm, sizeof(data.comm)); 37*387f9dfdSAndroid Build Coastguard Worker/* 38*387f9dfdSAndroid Build Coastguard Worker * The following deals with kernel version changes (in mainline 4.14 and 5.12, although 39*387f9dfdSAndroid Build Coastguard Worker * it may be backported to earlier kernels) with how the disk name is accessed. 40*387f9dfdSAndroid Build Coastguard Worker * We handle both pre- and post-change versions here. Please avoid kernel 41*387f9dfdSAndroid Build Coastguard Worker * version tests like this as much as possible: they inflate the code, test, 42*387f9dfdSAndroid Build Coastguard Worker * and maintenance burden. 43*387f9dfdSAndroid Build Coastguard Worker */ 44*387f9dfdSAndroid Build Coastguard Worker#ifdef bio_dev 45*387f9dfdSAndroid Build Coastguard Worker struct gendisk *bi_disk = bio->__BI_DISK__; 46*387f9dfdSAndroid Build Coastguard Worker#else 47*387f9dfdSAndroid Build Coastguard Worker struct gendisk *bi_disk = bio->bi_bdev->bd_disk; 48*387f9dfdSAndroid Build Coastguard Worker#endif 49*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&data.disk, sizeof(data.disk), bi_disk->disk_name); 50*387f9dfdSAndroid Build Coastguard Worker events.perf_submit(ctx, &data, sizeof(data)); 51*387f9dfdSAndroid Build Coastguard Worker return 0; 52*387f9dfdSAndroid Build Coastguard Worker} 53*387f9dfdSAndroid Build Coastguard Worker""" 54*387f9dfdSAndroid Build Coastguard Worker 55*387f9dfdSAndroid Build Coastguard Workerif BPF.kernel_struct_has_field('bio', 'bi_bdev') == 1: 56*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('__BI_DISK__', 'bi_bdev->bd_disk') 57*387f9dfdSAndroid Build Coastguard Workerelse: 58*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('__BI_DISK__', 'bi_disk') 59*387f9dfdSAndroid Build Coastguard Worker 60*387f9dfdSAndroid Build Coastguard Worker# initialize BPF 61*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text) 62*387f9dfdSAndroid Build Coastguard Worker 63*387f9dfdSAndroid Build Coastguard Worker# header 64*387f9dfdSAndroid Build Coastguard Workerprint("Tracing md flush requests... Hit Ctrl-C to end.") 65*387f9dfdSAndroid Build Coastguard Workerprint("%-8s %-7s %-16s %s" % ("TIME", "PID", "COMM", "DEVICE")) 66*387f9dfdSAndroid Build Coastguard Worker 67*387f9dfdSAndroid Build Coastguard Worker# process event 68*387f9dfdSAndroid Build Coastguard Workerdef print_event(cpu, data, size): 69*387f9dfdSAndroid Build Coastguard Worker event = b["events"].event(data) 70*387f9dfdSAndroid Build Coastguard Worker print("%-8s %-7d %-16s %s" % (strftime("%H:%M:%S"), event.pid, 71*387f9dfdSAndroid Build Coastguard Worker event.comm.decode('utf-8', 'replace'), 72*387f9dfdSAndroid Build Coastguard Worker event.disk.decode('utf-8', 'replace'))) 73*387f9dfdSAndroid Build Coastguard Worker 74*387f9dfdSAndroid Build Coastguard Worker# read events 75*387f9dfdSAndroid Build Coastguard Workerb["events"].open_perf_buffer(print_event) 76*387f9dfdSAndroid Build Coastguard Workerwhile 1: 77*387f9dfdSAndroid Build Coastguard Worker try: 78*387f9dfdSAndroid Build Coastguard Worker b.perf_buffer_poll() 79*387f9dfdSAndroid Build Coastguard Worker except KeyboardInterrupt: 80*387f9dfdSAndroid Build Coastguard Worker exit() 81