BPF_CORE_READ issue with nvme_submit_cmd kprobe.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



While attempting to learn more about BPF and libbpf, I ran into an
issue I can't quite seem to resolve.

While writing some tools to practice tracing with libbpf, I came
across a situation where I get an error when using BPF_CORE_READ,
which appears to be that CO-RE relocation failed to find a
corresponding field. Compilation doesn't complain, just when I try to
execute.

Error Message:
---------------------------------------------
8: (85) call unknown#195896080
invalid func unknown#195896080

I'm using the Makefile from libbpf-bootstrap to build my program. The
other example programs build and execute properly, and I've also
successfully used tracepoints to trace the nvme_setup_cmd and
nvme_complete_rq functions. My issue appears to be when I attempt to
use kprobes for the nvme_submit_cmd function.

In the program I'm attempting to trace the nvme_command structure to
get the opcode of the command in the function nvme_submit_cmd. I'm
using Rocky Linux (RedHat based distro) with their kernel version of
4.18. I verified the structures and interfaces in the source code, vs
the default 4.18 version of the kernel and made the appropriate
changes.

traceopcode.bpf.c
---------------------------------------------
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
#include "traceopcode.h"

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

struct {
    __uint(type, BPF_MAP_TYPE_RINGBUF);
    __uint(max_entries, 1024 * 1024);
} ring_buffer SEC(".maps");

struct nvme_common_command {
    __u8         opcode;
} __attribute__((preserve_access_index));

struct nvme_command {
    union {
        struct nvme_common_command common;
    };
} __attribute__((preserve_access_index));

SEC("kprobe/nvme_submit_cmd")
int BPF_KPROBE(nvme_submit_cmd, void *nvmeq, struct nvme_command *cmd,
bool write_sq)
{
    struct opcode_event *e;

    e = bpf_ringbuf_reserve(&ring_buffer, sizeof(*e), 0);
    if (!e)
        return 0;

    e->opcode = BPF_CORE_READ(cmd, common.opcode);
    //e->opcode = cmd->common.opcode;
    bpf_ringbuf_submit(e, 0);

   return 0;
}


traceopcode.h
---------------------------------------------
#ifndef __TRACEOPCODE_H
#define __TRACEOPCODE_H

struct opcode_event {
    __u8 opcode;
};

#endif


My userspace code is basically the same as the bootstrap example, with
a modification to the handler that just prints out the opcode from the
opcode_event structure. My guess is that I have some problem with how
I'm defining the structs that I'm using for nvme_command, as they
aren't part of vmlinux and need to be defined in my bpf program.

Any help or guidance would be appreciated.

Thanks,
John Mazzie



[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux