-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ff4c656
commit bbc7dbc
Showing
11 changed files
with
1,005 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
#include "vmlinux.h" | ||
#include "bpf_tracing.h" | ||
#include "bpf_helpers.h" | ||
|
||
#include "netdata_core.h" | ||
#include "netdata_disk.h" | ||
|
||
/************************************************************************************ | ||
* | ||
* MAPS | ||
* | ||
***********************************************************************************/ | ||
|
||
//Hardware | ||
struct { | ||
__uint(type, BPF_MAP_TYPE_PERCPU_HASH); | ||
__type(key, block_key_t); | ||
__type(value, __u64); | ||
__uint(max_entries, NETDATA_DISK_HISTOGRAM_LENGTH); | ||
} tbl_disk_iocall SEC(".maps"); | ||
|
||
// Temporary use only | ||
struct { | ||
__uint(type, BPF_MAP_TYPE_PERCPU_HASH); | ||
__type(key, netdata_disk_key_t); | ||
__type(value, __u64); | ||
__uint(max_entries, 8192); | ||
} tmp_disk_tp_stat SEC(".maps"); | ||
|
||
|
||
/************************************************************************************ | ||
* | ||
* DISK SECTION | ||
* | ||
***********************************************************************************/ | ||
|
||
SEC("tracepoint/block/block_rq_issue") | ||
int netdata_block_rq_issue(struct netdata_block_rq_issue *ptr) | ||
{ | ||
// blkid generates these and we're not interested in them | ||
if (!ptr->dev) | ||
return 0; | ||
|
||
netdata_disk_key_t key = {}; | ||
key.dev = ptr->dev; | ||
key.sector = ptr->sector; | ||
|
||
if (key.sector < 0) | ||
key.sector = 0; | ||
|
||
__u64 value = bpf_ktime_get_ns(); | ||
|
||
bpf_map_update_elem(&tmp_disk_tp_stat, &key, &value, BPF_ANY); | ||
|
||
return 0; | ||
} | ||
|
||
SEC("tracepoint/block/block_rq_complete") | ||
int netdata_block_rq_complete(struct netdata_block_rq_complete *ptr) | ||
{ | ||
__u64 *fill; | ||
netdata_disk_key_t key = {}; | ||
block_key_t blk = {}; | ||
key.dev = ptr->dev; | ||
key.sector = ptr->sector; | ||
|
||
if (key.sector < 0) | ||
key.sector = 0; | ||
|
||
fill = bpf_map_lookup_elem(&tmp_disk_tp_stat ,&key); | ||
if (!fill) | ||
return 0; | ||
|
||
// calculate and convert to microsecond | ||
u64 curr = bpf_ktime_get_ns(); | ||
__u64 data, *update; | ||
curr -= *fill; | ||
curr /= 1000; | ||
|
||
blk.bin = libnetdata_select_idx(curr, NETDATA_FS_MAX_BINS_POS); | ||
blk.dev = netdata_new_encode_dev(ptr->dev); | ||
|
||
// Update IOPS | ||
update = bpf_map_lookup_elem(&tbl_disk_iocall ,&blk); | ||
if (update) { | ||
libnetdata_update_u64(update, 1); | ||
} else { | ||
data = 1; | ||
bpf_map_update_elem(&tbl_disk_iocall, &blk, &data, BPF_ANY); | ||
} | ||
|
||
bpf_map_delete_elem(&tmp_disk_tp_stat, &key); | ||
|
||
return 0; | ||
} | ||
|
||
char _license[] SEC("license") = "GPL"; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <stdint.h> | ||
#include <getopt.h> | ||
|
||
#define _GNU_SOURCE /* See feature_test_macros(7) */ | ||
#define __USE_GNU | ||
#include <fcntl.h> | ||
#include <unistd.h> | ||
|
||
#include "netdata_tests.h" | ||
|
||
#include "disk.skel.h" | ||
|
||
// Copied and redefined from ../include/netdata_disk.h | ||
typedef struct block_key { | ||
uint32_t bin; | ||
uint32_t dev; | ||
} block_key_t; | ||
|
||
static inline int ebpf_load_and_attach(struct disk_bpf *obj) | ||
{ | ||
int ret = disk_bpf__load(obj); | ||
if (ret) { | ||
fprintf(stderr, "failed to load BPF object: %d\n", ret); | ||
return -1; | ||
} | ||
|
||
ret = disk_bpf__attach(obj); | ||
if (!ret) { | ||
fprintf(stdout, "Disk loaded with success\n"); | ||
} | ||
|
||
return ret; | ||
} | ||
|
||
static void ebpf_update_table(int global) | ||
{ | ||
block_key_t idx = { .bin = 0, .dev = 0}; | ||
unsigned char value = 'a'; | ||
int ret = bpf_map_update_elem(global, &idx, &value, 0); | ||
if (ret) | ||
fprintf(stderr, "Cannot insert value to global table."); | ||
} | ||
|
||
static int disk_read_array(int fd, int ebpf_nprocs) | ||
{ | ||
uint64_t *stored = calloc((size_t)ebpf_nprocs, sizeof(uint64_t)); | ||
if (!stored) | ||
return 2; | ||
|
||
uint64_t counter = 0; | ||
block_key_t idx = { .bin = 0, .dev = 0}; | ||
if (!bpf_map_lookup_elem(fd, &idx, stored)) { | ||
int j; | ||
for (j = 0; j < ebpf_nprocs; j++) { | ||
counter += stored[j]; | ||
} | ||
} | ||
|
||
free(stored); | ||
|
||
if (counter) { | ||
fprintf(stdout, "Data stored with success\n"); | ||
return 0; | ||
} | ||
|
||
return 2; | ||
} | ||
|
||
static int ebpf_disk_tests() | ||
{ | ||
struct disk_bpf *obj = NULL; | ||
int ebpf_nprocs = (int)sysconf(_SC_NPROCESSORS_ONLN); | ||
|
||
obj = disk_bpf__open(); | ||
if (!obj) { | ||
fprintf(stderr, "Cannot open or load BPF object\n"); | ||
|
||
return 2; | ||
} | ||
|
||
int ret = ebpf_load_and_attach(obj); | ||
if (!ret) { | ||
int fd = bpf_map__fd(obj->maps.tbl_disk_iocall); | ||
ebpf_update_table(fd); | ||
|
||
ret = disk_read_array(fd, ebpf_nprocs); | ||
if (ret) | ||
fprintf(stderr, "Cannot read global table\n"); | ||
} else | ||
fprintf(stderr ,"%s", NETDATA_CORE_DEFAULT_ERROR); | ||
|
||
disk_bpf__destroy(obj); | ||
|
||
return ret; | ||
} | ||
|
||
int main(int argc, char **argv) | ||
{ | ||
static struct option long_options[] = { | ||
{"help", no_argument, 0, 'h' }, | ||
{0, 0, 0, 0} | ||
}; | ||
|
||
int option_index = 0; | ||
while (1) { | ||
int c = getopt_long(argc, argv, "", long_options, &option_index); | ||
if (c == -1) | ||
break; | ||
|
||
switch (c) { | ||
case 'h': { | ||
ebpf_tracepoint_help("Disk"); | ||
exit(0); | ||
} | ||
default: { | ||
break; | ||
} | ||
} | ||
} | ||
|
||
int ret = netdata_ebf_memlock_limit(); | ||
if (ret) { | ||
fprintf(stderr, "Cannot increase memory: error = %d\n", ret); | ||
return 1; | ||
} | ||
|
||
return ebpf_disk_tests(); | ||
} | ||
|
Oops, something went wrong.