Skip to content

Commit dbf1763

Browse files
rgushchinKernel Patches Daemon
authored andcommitted
sched: psi: implement bpf_psi_create_trigger() kfunc
Implement a new bpf_psi_create_trigger() bpf kfunc, which allows to create new psi triggers and attach them to cgroups or be system-wide. Created triggers will exist until the struct ops is loaded and if they are attached to a cgroup until the cgroup exists. Due to a limitation of 5 arguments, the resource type and the "full" bit are squeezed into a single u32. Signed-off-by: Roman Gushchin <[email protected]>
1 parent 5748e69 commit dbf1763

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

kernel/sched/bpf_psi.c

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,83 @@ static const struct bpf_verifier_ops bpf_psi_verifier_ops = {
156156
.is_valid_access = bpf_psi_ops_is_valid_access,
157157
};
158158

159+
__bpf_kfunc_start_defs();
160+
161+
/**
162+
* bpf_psi_create_trigger - Create a PSI trigger
163+
* @bpf_psi: bpf_psi struct to attach the trigger to
164+
* @cgroup_id: cgroup Id to attach the trigger; 0 for system-wide scope
165+
* @resource: resource to monitor (PSI_MEM, PSI_IO, etc) and the full bit.
166+
* @threshold_us: threshold in us
167+
* @window_us: window in us
168+
*
169+
* Creates a PSI trigger and attached is to bpf_psi. The trigger will be
170+
* active unless bpf struct ops is unloaded or the corresponding cgroup
171+
* is deleted.
172+
*
173+
* Resource's most significant bit encodes whether "some" or "full"
174+
* PSI state should be tracked.
175+
*
176+
* Returns 0 on success and the error code on failure.
177+
*/
178+
__bpf_kfunc int bpf_psi_create_trigger(struct bpf_psi *bpf_psi,
179+
u64 cgroup_id, u32 resource,
180+
u32 threshold_us, u32 window_us)
181+
{
182+
enum psi_res res = resource & ~BPF_PSI_FULL;
183+
bool full = resource & BPF_PSI_FULL;
184+
struct psi_trigger_params params;
185+
struct cgroup *cgroup __maybe_unused = NULL;
186+
struct psi_group *group;
187+
struct psi_trigger *t;
188+
int ret = 0;
189+
190+
if (res >= NR_PSI_RESOURCES)
191+
return -EINVAL;
192+
193+
#ifdef CONFIG_CGROUPS
194+
if (cgroup_id) {
195+
cgroup = cgroup_get_from_id(cgroup_id);
196+
if (IS_ERR_OR_NULL(cgroup))
197+
return PTR_ERR(cgroup);
198+
199+
group = cgroup_psi(cgroup);
200+
} else
201+
#endif
202+
group = &psi_system;
203+
204+
params.type = PSI_BPF;
205+
params.bpf_psi = bpf_psi;
206+
params.privileged = capable(CAP_SYS_RESOURCE);
207+
params.res = res;
208+
params.full = full;
209+
params.threshold_us = threshold_us;
210+
params.window_us = window_us;
211+
212+
t = psi_trigger_create(group, &params);
213+
if (IS_ERR(t))
214+
ret = PTR_ERR(t);
215+
else
216+
t->cgroup_id = cgroup_id;
217+
218+
#ifdef CONFIG_CGROUPS
219+
if (cgroup)
220+
cgroup_put(cgroup);
221+
#endif
222+
223+
return ret;
224+
}
225+
__bpf_kfunc_end_defs();
226+
227+
BTF_KFUNCS_START(bpf_psi_kfuncs)
228+
BTF_ID_FLAGS(func, bpf_psi_create_trigger, KF_TRUSTED_ARGS)
229+
BTF_KFUNCS_END(bpf_psi_kfuncs)
230+
231+
static const struct btf_kfunc_id_set bpf_psi_kfunc_set = {
232+
.owner = THIS_MODULE,
233+
.set = &bpf_psi_kfuncs,
234+
};
235+
159236
static int bpf_psi_ops_reg(void *kdata, struct bpf_link *link)
160237
{
161238
struct bpf_psi_ops *ops = kdata;
@@ -238,6 +315,13 @@ static int __init bpf_psi_struct_ops_init(void)
238315
if (!bpf_psi_wq)
239316
return -ENOMEM;
240317

318+
err = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS,
319+
&bpf_psi_kfunc_set);
320+
if (err) {
321+
pr_warn("error while registering bpf psi kfuncs: %d", err);
322+
goto err;
323+
}
324+
241325
err = register_bpf_struct_ops(&bpf_psi_bpf_ops, bpf_psi_ops);
242326
if (err) {
243327
pr_warn("error while registering bpf psi struct ops: %d", err);

0 commit comments

Comments
 (0)