Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace PID with Task Pointer in Rusty #713

Merged
merged 1 commit into from
Oct 4, 2024

Conversation

likewhatevs
Copy link
Contributor

@likewhatevs likewhatevs commented Oct 1, 2024

I wasnt't able to reopen #672 because I force pushed (just learned about that limit).

This is a continuation of that PR.

I closed that PR and opened #710 because, while the first PR's approach passed stress tests and seemed to work, it kind of didn't make sense that I could deref the casted pointer to task_struct.

I updated that initial PR to explicltly deref that casted pointer to confirm this works/the verifier allows it and it seems to work so, this works?

see latest comment

@likewhatevs likewhatevs marked this pull request as draft October 1, 2024 17:38
@vax-r
Copy link
Contributor

vax-r commented Oct 2, 2024

Wouldn't this design throw away the origin safety provided by bpf_task_from_pid() ? It was able to perform reference count on the task_struct .
Using a map to store is awesome but it seems that we do not have mechanism to cleanup the unused <k, v> pair in the map, as the time going, the map size can grow really big, even it's acceptable, we would still like to avoid redundant memory usage , maybe having that implemented will be nice?

@vax-r
Copy link
Contributor

vax-r commented Oct 2, 2024

Btw I want to ask what's the actual cause of Failed to lookup task %d ?

@likewhatevs
Copy link
Contributor Author

likewhatevs commented Oct 2, 2024

Wouldn't this design throw away the origin safety provided by bpf_task_from_pid() ? It was able to perform reference count on the task_struct .

That was not apparent to me but now that you mention it, this sounds like it might be what I've been fighting the verifier over wrt/ all the different attempts to make this work (i.e. for every attempt, once the code makes sense, instruction count skyrockets and the verifier refuses to pass this code).

Using a map to store is awesome but it seems that we do not have mechanism to cleanup the unused <k, v> pair in the map, as the time going, the map size can grow really big, even it's acceptable, we would still like to avoid redundant memory usage , maybe having that implemented will be nice?

I'm going to give that a try using bpf_task_from_pid and see if that can get the verifier to allow this code to run.

Btw I want to ask what's the actual cause of Failed to lookup task %d ?

tl;dr -- pid's can change (but task struct ptrs cannot): #610

@likewhatevs likewhatevs changed the title Have rusty track task pointer Have rusty not error when pid missing Oct 2, 2024
@likewhatevs
Copy link
Contributor Author

I think this is the best we (or well, at least I) can do atm.

So like, I tried a few ways of tracking the association between the initial pid of a task struct and the pointer of the task struct.

My most recent attempts errored at null-checking the task context read using that association:

; if (!taskc) goto free_task; @ main.bpf.c:456
372: (15) if r3 == 0x0 goto pc+27
R3 !read_ok
processed 11065 insns (limit 1000000) max_states_per_insn 8 total_states 740 peak_states 298 mark_read 18
-- END PROG LOAD LOG --

Unless I'm reading something wrong or misunderstand something, I think this is the best we can do ATM (i.e. until it's possible to null check the retrieved variable).

I think this might be alright though because like, tests do pass and logs on those tests do not have stalls (which, I think, is the main reason to be concerned we are tracking everything).

@likewhatevs likewhatevs marked this pull request as ready for review October 2, 2024 18:49
@vax-r
Copy link
Contributor

vax-r commented Oct 3, 2024

I think this might be alright though because like, tests do pass and logs on those tests do not have stalls (which, I think, is the main reason to be concerned we are tracking everything).

It seems to me that what the commit does is only refactor the origin code , rather than actually changing any logic or mechanism when dealing with pid and task_struct, how can it pass this time ? It seems confusing to me.

@likewhatevs
Copy link
Contributor Author

It seems to me that what the commit does is only refactor the origin code , rather than actually changing any logic or mechanism when dealing with pid and task_struct, how can it pass this time ? It seems confusing to me.

This is correct. What I am wondering is if the current behavior (without that exception being thrown) is problematic. I would think I would see a stall if it were if I understand how things work correctly now, but I'm not super certain of that.

@hodgesds
Copy link
Contributor

hodgesds commented Oct 3, 2024

This is correct. What I am wondering is if the current behavior (without that exception being thrown) is problematic. I would think I would see a stall if it were if I understand how things work correctly now, but I'm not super certain of that.

I think the idea is that if correct scheduling decisions can't be made by the the scheduler it's better to exit (the scheduler) rather than making bad scheduling decisions. There's still some bugs in rusty, so in some ways it maybe is better to fail fast in more places. In this case of looking up the task context I think it's probably ok to bail the scheduler, because if the task context is lost/incorrect then making correct scheduling decisions is probably not handled correctly elsewhere.

@hodgesds hodgesds closed this Oct 3, 2024
@hodgesds hodgesds reopened this Oct 3, 2024
@likewhatevs
Copy link
Contributor Author

I think the idea is that if correct scheduling decisions can't be made by the the scheduler it's better to exit (the scheduler) rather than making bad scheduling decisions.

That makes sense.

In this case of looking up the task context I think it's probably ok to bail the scheduler, because if the task context is lost/incorrect then making correct scheduling decisions is probably not handled correctly elsewhere.

This is the part where like, IDK. So like, if we lost the task, it wouldn't be scheduled, and we would see a stall?

If that is correct, then maybe (like, super maybe, idk), we're getting the task again after the pid change happens, and because we're keying off the PID, we're treating task as an entirely new task (hence no stall)?

@hodgesds
Copy link
Contributor

hodgesds commented Oct 3, 2024

This is the part where like, IDK. So like, if we lost the task, it wouldn't be scheduled, and we would see a stall?

I think the problem with stress-ng tests is that with the --fork tests the tasks come and go really fast, I'm not sure if there's an easy way to trigger the behavior (maybe compiling the kernel like in #684) and see what happens with this change. Maybe do a kernel build with something crazy like ````make -j $(nproc * 2)```.

@likewhatevs
Copy link
Contributor Author

I think the problem with stress-ng tests is that with the --fork tests the tasks come and go really fast, I'm not sure if there's an easy way to trigger the behavior (maybe compiling the kernel like in #684) and see what happens with this change. Maybe do a kernel build with something crazy like ````make -j $(nproc * 2)```.

gonna run it on laptop for a day and do the terraria/compile test/see if I can find bad behavior, good idea, thx!

@likewhatevs likewhatevs marked this pull request as draft October 3, 2024 16:47
@likewhatevs likewhatevs changed the title Have rusty not error when pid missing Replace PID with Task Pointer in Rusty Oct 4, 2024
@likewhatevs likewhatevs marked this pull request as ready for review October 4, 2024 18:49
@likewhatevs likewhatevs marked this pull request as draft October 4, 2024 18:51
@likewhatevs likewhatevs marked this pull request as ready for review October 4, 2024 18:55
@likewhatevs
Copy link
Contributor Author

Alright so I think I finally got this (and learned a ton along the way).

This PR now has Rusty use Task pointer casted to u64 to track tasks instead of pid.

A couple things I learned:

In bpf, you can't cast "trusted pointers". I don't fully get it, but t_to_tptr makes the cast work w/ the verifier.

Making functions static makes some problems go away, but can also super quickly drive things over the instruction limit.

More interestingly, I tried only grabbing pid via probe_read (rather than a pointer to task_struct), and to then grab task_struct via bpf_task_from_pid (because maybe the bpf locking could be useful/I was curious).

What I found is that is super racy (i.e. adding a counter and a while loop made stress test last longer while before failing with a missing pid error), so I kind of think we need to not use bpf_task_from_pid anywhere.

Copy link
Contributor

@hodgesds hodgesds left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will work!

Replace PID with Task Pointer in Rusty

Fixes: sched-ext#610
@likewhatevs likewhatevs added this pull request to the merge queue Oct 4, 2024
Merged via the queue into sched-ext:main with commit 719e98a Oct 4, 2024
19 checks passed
@likewhatevs likewhatevs deleted the have-rusty-track-tgid branch October 4, 2024 22:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants