Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fs_watcher:给block_rq_issue这个bpf程序添加了统计每个进程的I/O总大小的功能 #912

Merged
merged 2 commits into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,61 @@

char LICENSE[] SEC("license") = "Dual BSD/GPL";

// 定义 ringbuf,用于传输事件信息
struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 256 * 1024);
} rb SEC(".maps");

// 这里挂载点必须是struct trace_event_raw_block_rq_completion *ctx
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 1024);
__type(key, u32); // 使用进程 PID 作为键
__type(value, u64); // I/O 总大小作为值
} io_size_map SEC(".maps");

SEC("tracepoint/block/block_rq_issue")
int tracepoint_block_rq_issue(struct trace_event_raw_block_rq_completion *ctx) {
struct event *e;
char comm[TASK_COMM_LEN];
u32 pid = bpf_get_current_pid_tgid() >> 32; // 获取进程 ID
u64 *size, total_size;

// 分配 ringbuf 空间
e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0);
if (!e) {
return 0; // 如果分配失败,提前返回
}

// 获取当前进程名
bpf_get_current_comm(e->comm, sizeof(e->comm));

// 填充事件数据
e->timestamp = bpf_ktime_get_ns();
e->dev = ctx->dev; // 读取设备号
e->sector = ctx->sector; // 读取扇区号
e->nr_sectors = ctx->nr_sector; // 读取扇区数
e->dev = ctx->dev;
e->sector = ctx->sector;
e->nr_sectors = ctx->nr_sector;

// 日志输出调试信息
bpf_printk("PID: %u, Sector: %d, nr_sectors: %d\n", pid, ctx->sector, ctx->nr_sector);

// 查找或初始化该进程的 I/O 总大小
size = bpf_map_lookup_elem(&io_size_map, &pid);
if (size) {
total_size = *size;
} else {
total_size = 0;
}

// 计算本次 I/O 请求的大小
const u64 sector_size = 512; // 标准扇区大小
total_size += ctx->nr_sector * sector_size;

// 更新 I/O 总大小
bpf_map_update_elem(&io_size_map, &pid, &total_size, BPF_ANY);

e->total_io = total_size;

// 获取进程名
bpf_get_current_comm(comm, sizeof(comm));
__builtin_memcpy(e->comm, comm, sizeof(comm));
// 日志输出当前总 I/O 大小
bpf_printk("Updated Total I/O for PID %u: %llu\n", pid, total_size);

// 提交事件
bpf_ringbuf_submit(e, 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
#include <bpf/libbpf.h>
#include "block_rq_issue.h"
#include "block_rq_issue.skel.h"
#include <inttypes.h> // For PRIu64
#include <stdint.h> // For uint32_t, uint64_t
#include <unistd.h> // For getpid()

static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
{
Expand All @@ -17,15 +20,15 @@ static void sig_handler(int sig)
exiting = true;
}

static int handle_event_block_rq_issue(void *ctx, void *data,unsigned long data_sz) {
static int handle_event_block_rq_issue(void *ctx, void *data, unsigned long data_sz) {
const struct event *e = data;

printf("%-10llu %-9d %-7d %-4d %-16s\n",
e->timestamp, e->dev, e->sector, e->nr_sectors,e->comm);

printf("%-10llu %-9d %-7d %-4d %-16s Total I/O: %" PRIu64 "\n",
e->timestamp, e->dev, e->sector, e->nr_sectors, e->comm, e->total_io);
return 0;
}


int main(int argc, char **argv)
{
struct ring_buffer *rb = NULL;
Expand Down Expand Up @@ -68,7 +71,7 @@ int main(int argc, char **argv)
goto cleanup;
}

printf("%-18s %-7s %-7s %-4s %-7s %-16s\n","TIME", "DEV", "SECTOR", "RWBS", "COUNT", "COMM");
printf("%-10s %-9s %-7s %-4s %-16s %-12s\n", "TIME", "DEV", "SECTOR", "RWBS", "COMM", "Total I/O");
while (!exiting) {
err = ring_buffer__poll(rb, 100 /* timeout, ms */);
/* Ctrl-C will cause -EINTR */
Expand All @@ -89,4 +92,4 @@ int main(int argc, char **argv)
block_rq_issue_bpf__destroy(skel);

return err < 0 ? -err : 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@

#define TASK_COMM_LEN 256

// 定义事件结构体
struct event {
long timestamp; // 时间戳
int dev; // 设备号
int sector; // 扇区号
int nr_sectors; // 扇区数
char comm[TASK_COMM_LEN]; // 进程名
int total_io; //I/O总大小
};

#endif // BLOCK_RQ_ISSUE
25 changes: 13 additions & 12 deletions eBPF_Supermarket/Filesystem_Subsystem/fs_watcher/fs_watcher.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ static const struct argp_option opts[] = {
{"write", 'w', 0, 0, "Print write system call report"},
{"disk_io_visit", 'd', 0, 0, "Print disk I/O visit report"},
{"block_rq_issue", 'b', 0, 0, "Print block I/O request submission events. Reports when block I/O requests are submitted to device drivers."},
{0} // 结束标记,用于指示选项列表的结束
};


Expand Down Expand Up @@ -185,12 +186,13 @@ int main(int argc,char **argv){

libbpf_set_strict_mode(LIBBPF_STRICT_ALL);

/* Set up libbpf errors and debug info callback */
libbpf_set_print(libbpf_print_fn);

/* Set up libbpf errors and debug info callback */
libbpf_set_print(libbpf_print_fn);

/* Cleaner handling of Ctrl-C */
signal(SIGINT, sig_handler);
signal(SIGTERM, sig_handler);
signal(SIGINT, sig_handler);
signal(SIGTERM, sig_handler);
signal(SIGALRM, sig_handler);


Expand All @@ -215,7 +217,7 @@ int main(int argc,char **argv){
}
}

static int handle_event_open(void *ctx, void *data, size_t data_sz)
static int handle_event_open(void *ctx, void *data, size_t data_sz)
{
struct event_open *e = (struct event_open *)data;
char *filename = strrchr(e->path_name_, '/');
Expand All @@ -226,7 +228,8 @@ int main(int argc,char **argv){
char comm[TASK_COMM_LEN];
int i = 0;
int map_fd = *(int *)ctx;//传递map得文件描述符



for (; i < e->n_; ++i) {
snprintf(fd_path, sizeof(fd_path), "/proc/%d/fd/%d", e->pid_,
i);
Expand Down Expand Up @@ -278,7 +281,6 @@ static int handle_event_write(void *ctx, void *data, size_t data_sz)
return 0;
}


static int handle_event_disk_io_visit(void *ctx, void *data,unsigned long data_sz) {
const struct event_disk_io_visit *e = data;

Expand All @@ -290,9 +292,8 @@ static int handle_event_disk_io_visit(void *ctx, void *data,unsigned long data_s

static int handle_event_block_rq_issue(void *ctx, void *data,unsigned long data_sz) {
const struct event_block_rq_issue *e = data;

printf("%-10llu %-9d %-7d %-4d %-16s\n",
e->timestamp, e->dev, e->sector, e->nr_sectors,e->comm);
printf("%-10llu %-9d %-7d %-4d %-16s Total I/O: %" PRIu64 "\n",
e->timestamp, e->dev, e->sector, e->nr_sectors, e->comm, e->total_io);

return 0;
}
Expand Down Expand Up @@ -366,7 +367,7 @@ static int process_block_rq_issue(struct block_rq_issue_bpf *skel_block_rq_issue
struct ring_buffer *rb;

LOAD_AND_ATTACH_SKELETON(skel_block_rq_issue,block_rq_issue);
printf("%-18s %-7s %-7s %-4s %-16s\n","TIME", "DEV", "SECTOR", "SECTORS","COMM");
printf("%-18s %-7s %-7s %-4s %-16s %-5sn","TIME", "DEV", "SECTOR", "SECTORS","COMM","Total_Size");
POLL_RING_BUFFER(rb, 1000, err);

block_rq_issue_cleanup:
Expand All @@ -375,4 +376,4 @@ static int process_block_rq_issue(struct block_rq_issue_bpf *skel_block_rq_issue

return err;

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ struct event_block_rq_issue {
int sector; // 扇区号
int nr_sectors; // 扇区数
char comm[TASK_COMM_LEN]; // 进程名
int total_io; //I/O总大小
};

#endif /* __MEM_WATCHER_H */
Loading