@@ -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+
159236static 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