Skip to content

Commit 823e381

Browse files
Kaitao Chengkawasaki
authored andcommitted
tools/ufq_iosched: add BPF example scheduler and build scaffolding
Add ufq_iosched as a simple example for the UFQ block I/O scheduler, In the ufq_simple example, we implement the eBPF struct_ops hooks the kernel exposes so we can exercise and validate the behavior and stability of the kernel UFQ scheduling framework. The Makefile and directory layout are modeled after sched_ext. This mirrors the sched_ext examples pattern so developers can experiment with user-defined queueing policies on top of IOSCHED_UFQ. Signed-off-by: Kaitao Cheng <[email protected]>
1 parent 8a33f2b commit 823e381

9 files changed

Lines changed: 1160 additions & 0 deletions

File tree

tools/ufq_iosched/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
tools/
2+
build/

tools/ufq_iosched/Makefile

Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
# Copyright (c) 2026 KylinSoft Corporation.
3+
# Copyright (c) 2026 Kaitao Cheng <[email protected]>
4+
include ../build/Build.include
5+
include ../scripts/Makefile.arch
6+
include ../scripts/Makefile.include
7+
8+
all: all_targets
9+
10+
ifneq ($(LLVM),)
11+
ifneq ($(filter %/,$(LLVM)),)
12+
LLVM_PREFIX := $(LLVM)
13+
else ifneq ($(filter -%,$(LLVM)),)
14+
LLVM_SUFFIX := $(LLVM)
15+
endif
16+
17+
CLANG_TARGET_FLAGS_arm := arm-linux-gnueabi
18+
CLANG_TARGET_FLAGS_arm64 := aarch64-linux-gnu
19+
CLANG_TARGET_FLAGS_hexagon := hexagon-linux-musl
20+
CLANG_TARGET_FLAGS_m68k := m68k-linux-gnu
21+
CLANG_TARGET_FLAGS_mips := mipsel-linux-gnu
22+
CLANG_TARGET_FLAGS_powerpc := powerpc64le-linux-gnu
23+
CLANG_TARGET_FLAGS_riscv := riscv64-linux-gnu
24+
CLANG_TARGET_FLAGS_s390 := s390x-linux-gnu
25+
CLANG_TARGET_FLAGS_x86 := x86_64-linux-gnu
26+
CLANG_TARGET_FLAGS := $(CLANG_TARGET_FLAGS_$(ARCH))
27+
28+
ifeq ($(CROSS_COMPILE),)
29+
ifeq ($(CLANG_TARGET_FLAGS),)
30+
$(error Specify CROSS_COMPILE or add '--target=' option to lib.mk)
31+
else
32+
CLANG_FLAGS += --target=$(CLANG_TARGET_FLAGS)
33+
endif # CLANG_TARGET_FLAGS
34+
else
35+
CLANG_FLAGS += --target=$(notdir $(CROSS_COMPILE:%-=%))
36+
endif # CROSS_COMPILE
37+
38+
CC := $(LLVM_PREFIX)clang$(LLVM_SUFFIX) $(CLANG_FLAGS) -fintegrated-as
39+
else
40+
CC := $(CROSS_COMPILE)gcc
41+
endif # LLVM
42+
43+
CURDIR := $(abspath .)
44+
TOOLSDIR := $(abspath ..)
45+
LIBDIR := $(TOOLSDIR)/lib
46+
BPFDIR := $(LIBDIR)/bpf
47+
TOOLSINCDIR := $(TOOLSDIR)/include
48+
BPFTOOLDIR := $(TOOLSDIR)/bpf/bpftool
49+
APIDIR := $(TOOLSINCDIR)/uapi
50+
GENDIR := $(abspath ../../include/generated)
51+
GENHDR := $(GENDIR)/autoconf.h
52+
53+
ifeq ($(O),)
54+
OUTPUT_DIR := $(CURDIR)/build
55+
else
56+
OUTPUT_DIR := $(O)/build
57+
endif # O
58+
OBJ_DIR := $(OUTPUT_DIR)/obj
59+
INCLUDE_DIR := $(OUTPUT_DIR)/include
60+
BPFOBJ_DIR := $(OBJ_DIR)/libbpf
61+
UFQOBJ_DIR := $(OBJ_DIR)/ufq_iosched
62+
BINDIR := $(OUTPUT_DIR)/bin
63+
BPFOBJ := $(BPFOBJ_DIR)/libbpf.a
64+
ifneq ($(CROSS_COMPILE),)
65+
HOST_BUILD_DIR := $(OBJ_DIR)/host/obj
66+
HOST_OUTPUT_DIR := $(OBJ_DIR)/host
67+
HOST_INCLUDE_DIR := $(HOST_OUTPUT_DIR)/include
68+
else
69+
HOST_BUILD_DIR := $(OBJ_DIR)
70+
HOST_OUTPUT_DIR := $(OUTPUT_DIR)
71+
HOST_INCLUDE_DIR := $(INCLUDE_DIR)
72+
endif
73+
HOST_BPFOBJ := $(HOST_BUILD_DIR)/libbpf/libbpf.a
74+
RESOLVE_BTFIDS := $(HOST_BUILD_DIR)/resolve_btfids/resolve_btfids
75+
DEFAULT_BPFTOOL := $(HOST_OUTPUT_DIR)/sbin/bpftool
76+
77+
VMLINUX_BTF_PATHS ?= $(if $(O),$(O)/vmlinux) \
78+
$(if $(KBUILD_OUTPUT),$(KBUILD_OUTPUT)/vmlinux) \
79+
../../vmlinux \
80+
/sys/kernel/btf/vmlinux \
81+
/boot/vmlinux-$(shell uname -r)
82+
VMLINUX_BTF ?= $(abspath $(firstword $(wildcard $(VMLINUX_BTF_PATHS))))
83+
ifeq ($(VMLINUX_BTF),)
84+
$(error Cannot find a vmlinux for VMLINUX_BTF at any of "$(VMLINUX_BTF_PATHS)")
85+
endif
86+
87+
BPFTOOL ?= $(DEFAULT_BPFTOOL)
88+
89+
ifneq ($(wildcard $(GENHDR)),)
90+
GENFLAGS := -DHAVE_GENHDR
91+
endif
92+
93+
CFLAGS += -g -O2 -rdynamic -pthread -Wall -Werror $(GENFLAGS) \
94+
-I$(INCLUDE_DIR) -I$(GENDIR) -I$(LIBDIR) \
95+
-I$(TOOLSINCDIR) -I$(APIDIR) -I$(CURDIR)/include
96+
97+
# Silence some warnings when compiled with clang
98+
ifneq ($(LLVM),)
99+
CFLAGS += -Wno-unused-command-line-argument
100+
endif
101+
102+
LDFLAGS += -lelf -lz -lpthread
103+
104+
IS_LITTLE_ENDIAN = $(shell $(CC) -dM -E - </dev/null | \
105+
grep 'define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__')
106+
107+
# Get Clang's default includes on this system, as opposed to those seen by
108+
# '-target bpf'. This fixes "missing" files on some architectures/distros,
109+
# such as asm/byteorder.h, asm/socket.h, asm/sockios.h, sys/cdefs.h etc.
110+
#
111+
# Use '-idirafter': Don't interfere with include mechanics except where the
112+
# build would have failed anyways.
113+
define get_sys_includes
114+
$(shell $(1) -v -E - </dev/null 2>&1 \
115+
| sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') \
116+
$(shell $(1) -dM -E - </dev/null | grep '__riscv_xlen ' | awk '{printf("-D__riscv_xlen=%d -D__BITS_PER_LONG=%d", $$3, $$3)}')
117+
endef
118+
119+
BPF_CFLAGS = -g -D__TARGET_ARCH_$(SRCARCH) \
120+
$(if $(IS_LITTLE_ENDIAN),-mlittle-endian,-mbig-endian) \
121+
-I$(CURDIR)/include -I$(CURDIR)/include/bpf-compat \
122+
-I$(INCLUDE_DIR) -I$(APIDIR) \
123+
-I../../include \
124+
$(call get_sys_includes,$(CLANG)) \
125+
-Wall -Wno-compare-distinct-pointer-types \
126+
-Wno-microsoft-anon-tag \
127+
-fms-extensions \
128+
-O2 -mcpu=v3
129+
130+
# sort removes libbpf duplicates when not cross-building
131+
MAKE_DIRS := $(sort $(OBJ_DIR)/libbpf $(HOST_BUILD_DIR)/libbpf \
132+
$(HOST_BUILD_DIR)/bpftool $(HOST_BUILD_DIR)/resolve_btfids \
133+
$(INCLUDE_DIR) $(UFQOBJ_DIR) $(BINDIR))
134+
135+
$(MAKE_DIRS):
136+
$(call msg,MKDIR,,$@)
137+
$(Q)mkdir -p $@
138+
139+
ifneq ($(CROSS_COMPILE),)
140+
$(BPFOBJ): $(wildcard $(BPFDIR)/*.[ch] $(BPFDIR)/Makefile) \
141+
$(APIDIR)/linux/bpf.h \
142+
| $(OBJ_DIR)/libbpf
143+
$(Q)$(MAKE) $(submake_extras) CROSS_COMPILE=$(CROSS_COMPILE) \
144+
-C $(BPFDIR) OUTPUT=$(OBJ_DIR)/libbpf/ \
145+
EXTRA_CFLAGS='-g -O0 -fPIC' \
146+
LDFLAGS="$(LDFLAGS)" \
147+
DESTDIR=$(OUTPUT_DIR) prefix= all install_headers
148+
endif
149+
150+
$(HOST_BPFOBJ): $(wildcard $(BPFDIR)/*.[ch] $(BPFDIR)/Makefile) \
151+
$(APIDIR)/linux/bpf.h \
152+
| $(HOST_BUILD_DIR)/libbpf
153+
$(Q)$(MAKE) $(submake_extras) -C $(BPFDIR) \
154+
OUTPUT=$(HOST_BUILD_DIR)/libbpf/ \
155+
ARCH= CROSS_COMPILE= CC="$(HOSTCC)" LD=$(HOSTLD) \
156+
EXTRA_CFLAGS='-g -O0 -fPIC' \
157+
DESTDIR=$(HOST_OUTPUT_DIR) prefix= all install_headers
158+
159+
$(DEFAULT_BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) \
160+
$(HOST_BPFOBJ) | $(HOST_BUILD_DIR)/bpftool
161+
$(Q)$(MAKE) $(submake_extras) -C $(BPFTOOLDIR) \
162+
ARCH= CROSS_COMPILE= CC="$(HOSTCC)" LD=$(HOSTLD) \
163+
EXTRA_CFLAGS='-g -O0' \
164+
OUTPUT=$(HOST_BUILD_DIR)/bpftool/ \
165+
LIBBPF_OUTPUT=$(HOST_BUILD_DIR)/libbpf/ \
166+
LIBBPF_DESTDIR=$(HOST_OUTPUT_DIR)/ \
167+
prefix= DESTDIR=$(HOST_OUTPUT_DIR)/ install-bin
168+
169+
$(INCLUDE_DIR)/vmlinux.h: $(VMLINUX_BTF) $(BPFTOOL) | $(INCLUDE_DIR)
170+
ifeq ($(VMLINUX_H),)
171+
$(call msg,GEN,,$@)
172+
$(Q)$(BPFTOOL) btf dump file $(VMLINUX_BTF) format c > $@
173+
else
174+
$(call msg,CP,,$@)
175+
$(Q)cp "$(VMLINUX_H)" $@
176+
endif
177+
178+
$(UFQOBJ_DIR)/%.bpf.o: %.bpf.c $(INCLUDE_DIR)/vmlinux.h include/ufq/*.h \
179+
| $(BPFOBJ) $(UFQOBJ_DIR)
180+
$(call msg,CLNG-BPF,,$(notdir $@))
181+
$(Q)$(CLANG) $(BPF_CFLAGS) -target bpf -c $< -o $@
182+
183+
$(INCLUDE_DIR)/%.bpf.skel.h: $(UFQOBJ_DIR)/%.bpf.o $(INCLUDE_DIR)/vmlinux.h $(BPFTOOL)
184+
$(eval sched=$(notdir $@))
185+
$(call msg,GEN-SKEL,,$(sched))
186+
$(Q)$(BPFTOOL) gen object $(<:.o=.linked1.o) $<
187+
$(Q)$(BPFTOOL) gen object $(<:.o=.linked2.o) $(<:.o=.linked1.o)
188+
$(Q)$(BPFTOOL) gen object $(<:.o=.linked3.o) $(<:.o=.linked2.o)
189+
$(Q)diff $(<:.o=.linked2.o) $(<:.o=.linked3.o)
190+
$(Q)$(BPFTOOL) gen skeleton $(<:.o=.linked3.o) name $(subst .bpf.skel.h,,$(sched)) > $@
191+
$(Q)$(BPFTOOL) gen subskeleton $(<:.o=.linked3.o) name $(subst .bpf.skel.h,,$(sched)) > $(@:.skel.h=.subskel.h)
192+
193+
UFQ_COMMON_DEPS := include/ufq/common.h include/ufq/simple_stat.h | $(BINDIR)
194+
195+
c-sched-targets = ufq_simple
196+
197+
$(addprefix $(BINDIR)/,$(c-sched-targets)): \
198+
$(BINDIR)/%: \
199+
$(filter-out %.bpf.c,%.c) \
200+
$(INCLUDE_DIR)/%.bpf.skel.h \
201+
$(UFQ_COMMON_DEPS)
202+
$(eval sched=$(notdir $@))
203+
$(CC) $(CFLAGS) -c $(sched).c -o $(UFQOBJ_DIR)/$(sched).o
204+
$(CC) -o $@ $(UFQOBJ_DIR)/$(sched).o $(BPFOBJ) $(LDFLAGS)
205+
206+
$(c-sched-targets): %: $(BINDIR)/%
207+
208+
install: all
209+
$(Q)mkdir -p $(DESTDIR)/usr/local/bin/
210+
$(Q)cp $(BINDIR)/* $(DESTDIR)/usr/local/bin/
211+
212+
clean:
213+
rm -rf $(OUTPUT_DIR) $(HOST_OUTPUT_DIR)
214+
rm -f *.o *.bpf.o *.bpf.skel.h *.bpf.subskel.h
215+
rm -f $(c-sched-targets)
216+
217+
help:
218+
@echo 'Building targets'
219+
@echo '================'
220+
@echo ''
221+
@echo ' all - Compile all schedulers'
222+
@echo ''
223+
@echo 'Alternatively, you may compile individual schedulers:'
224+
@echo ''
225+
@printf ' %s\n' $(c-sched-targets)
226+
@echo ''
227+
@echo 'For any scheduler build target, you may specify an alternative'
228+
@echo 'build output path with the O= environment variable. For example:'
229+
@echo ''
230+
@echo ' O=/tmp/ufq_iosched make all'
231+
@echo ''
232+
@echo 'will compile all schedulers, and emit the build artifacts to'
233+
@echo '/tmp/ufq_iosched/build.'
234+
@echo ''
235+
@echo ''
236+
@echo 'Installing targets'
237+
@echo '=================='
238+
@echo ''
239+
@echo ' install - Compile and install all schedulers to /usr/bin.'
240+
@echo ' You may specify the DESTDIR= environment variable'
241+
@echo ' to indicate a prefix for /usr/bin. For example:'
242+
@echo ''
243+
@echo ' DESTDIR=/tmp/ufq_iosched make install'
244+
@echo ''
245+
@echo ' will build the schedulers in CWD/build, and'
246+
@echo ' install the schedulers to /tmp/ufq_iosched/usr/bin.'
247+
@echo ''
248+
@echo ''
249+
@echo 'Cleaning targets'
250+
@echo '================'
251+
@echo ''
252+
@echo ' clean - Remove all generated files'
253+
254+
all_targets: $(c-sched-targets)
255+
256+
.PHONY: all all_targets $(c-sched-targets) clean help
257+
258+
# delete failed targets
259+
.DELETE_ON_ERROR:
260+
261+
# keep intermediate (.bpf.skel.h, .bpf.o, etc) targets
262+
.SECONDARY:

0 commit comments

Comments
 (0)