Use impl_flags! in Rust Binder - #4
Conversation
In the current Rust Binder driver, internal state variables (thread looper states, deferred work, and transaction configurations) are represented as raw integers and manipulated using manual bitwise operations. This approach lacks type safety. Because the compiler treats all integers identically, it is possible to pass a thread looper flag into a function expecting a transaction flag without triggering compile-time warnings. These cross-contamination errors compile cleanly but can cause runtime bugs or undefined behavior. This patch series resolves this issue by migrating these raw integer bitmaps (`defer_work`, `looper_flags`, `flags`) to strongly-typed bitmasks using the `kernel::impl_flags!` macro. Functions now accept specific, distinct types rather than generic integers, preventing flags from being mixed up. This transition also replaces manual bitwise arithmetic with readable, safe methods. Based on top of: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git # Describe the purpose of this series. The information you put here # will be used by the project maintainer to make a decision whether # your patches should be reviewed, and in what priority order. Please be # very detailed and link to any relevant discussions or sites that the # maintainer can review to better understand your proposed changes. If you # only have a single patch in your series, the contents of the cover # letter will be appended to the "under-the-cut" portion of the patch. # Lines starting with # will be removed from the cover letter. You can # use them to add notes or reminders to yourself. If you want to use # markdown headers in your cover letter, start the line with ">#". # You can add trailers to the cover letter. Any email addresses found in # these trailers will be added to the addresses specified/generated # during the b4 send stage. You can also run "b4 prep --auto-to-cc" to # auto-populate the To: and Cc: trailers based on the code being # modified. Change-Id: I8375178251d97e7ad784a6ccd8c108c0d2d2b2eb Signed-off-by: Jahnavi MN <jahnavimn@google.com> --- b4-submit-tracking --- # This section is used internally by b4 prep for tracking purposes. { "series": { "revision": 1, "change-id": "20260715-b4-rust_binder_impl_flags-e53b4ebca85d", "prefixes": [] } }
|
|
||
| if self.flags & old.flags & (TF_ONE_WAY | TF_UPDATE_TXN) != (TF_ONE_WAY | TF_UPDATE_TXN) { | ||
| let required = TransactionFlag::OneWay | TransactionFlag::UpdateTxn; | ||
| if !self.flags.contains_all(required) || !old.flags.contains_all(required) { |
There was a problem hiding this comment.
This is a super minor thing, but I would find it easier to read like this.
| if !self.flags.contains_all(required) || !old.flags.contains_all(required) { | |
| if !(self.flags.contains_all(required) && old.flags.contains_all(required)) { |
| #[inline] | ||
| pub(crate) fn is_oneway(&self) -> bool { | ||
| self.flags & TF_ONE_WAY != 0 | ||
| self.flags.contains(TransactionFlag::OneWay) |
There was a problem hiding this comment.
We check flags.contains(TransactionFlag::OneWay) super often. It might be nice to add a helper function called is_oneway() on TransactionFlags type to make these calls even shorter and easier to read.
- Define `DeferWorks(u8)` and `DeferWork` enum using `bit_u8` offsets. - Change `ProcessInner.defer_work` type from `u8` to `DeferWorks`. - Update `Process::release()` and `Process::flush()` to check for empty states using `DeferWorks::empty()`. - Update the workqueue runner to inspect flags using `.contains()`.
- Define `LooperFlags(u32)` and `LooperFlag` enum with 7 variants. - Change `InnerThread.looper_flags` type to `LooperFlags`. - Update looper state transitions and checks to use type-safe methods. - Convert `looper_flags` to `u32` for hex formatting in `debug_print`.
- Define `TransactionFlags(u32)` and `TransactionFlag` with 4 variants. - Change flags field type to `TransactionFlags` in structs. - Add `is_oneway` helper on `TransactionFlags` to simplify checks. - Update `can_replace` logic to use type-safe combined flag checks. - Convert `flags` to `u32` for FFI boundaries and logging.
c0f5662 to
3602828
Compare
Darksonn
left a comment
There was a problem hiding this comment.
You need to ensure that the commit messages:
- Have your Signed-off-by tag.
- Do not have a Change-Id.
| /// Represents a single deferred work category. | ||
| #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
| pub enum DeferWork { | ||
| Flush = bit_u8(0), | ||
| Release = bit_u8(1), | ||
| } |
There was a problem hiding this comment.
Looking at this code I am thinking "why do you have to write 0 and 1 on these? Can't you just leave them out and let the macro pick bits for me". After all, with a normal macro you can just write:
enum MyMacro {
Variant1,
Variant2,
}I know the macro doesn't support this yet, but maybe it should?
Totally optional if you want to implement that or not.
do_thaw_all() iterates over all superblocks via __iterate_supers() with SUPER_ITER_EXCL, which acquires s_umount exclusively before calling the callback and releases it afterwards. However, the callback do_thaw_all_callback() calls thaw_super_locked() which unconditionally releases s_umount on every code path. This results in a second unlock attempt in __iterate_supers() that corrupts the rwsem state, triggering a DEBUG_RWSEMS warning: [ 182.601148] sysrq: Emergency Thaw of all frozen filesystems [ 182.601865] ------------[ cut here ]------------ [ 182.602375] DEBUG_RWSEMS_WARN_ON((rwsem_owner(sem) != current) && !rwsem_test_oflags(sem, RWSEM_NONSPINNABLE)): count = 0x0, magic = 0xffff99b1011e5870, owner = 0x0, curr 0xffff99b101b06c80, list not empty [ 182.603817] WARNING: kernel/locking/rwsem.c:1412 at up_write+0xa3/0x170, CPU#2: kworker/2:1/53 [ 182.604578] Modules linked in: [ 182.604864] CPU: 2 UID: 0 PID: 53 Comm: kworker/2:1 Not tainted 7.2.0-rc4-00001-gbd3bd93ea98a-dirty #4 PREEMPT(lazy) [ 182.605711] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1kylin1 04/01/2014 [ 182.606417] Workqueue: events do_thaw_all [ 182.606750] RIP: 0010:up_write+0xaf/0x170 [ 182.607076] Code: 19 3a 92 48 0f 44 c2 48 8b 55 08 48 8b 55 00 4c 8b 45 08 48 8b 55 00 48 8d 3d ad 91 e0 01 48 8b 4d 20 50 48 c7 c6 f0 8c 26 92 <67> 48 0f b9 3a e8 d7 93 4e 00 58 eb 81 48 83 7f 18 00 48 c7 c2 8d [ 182.608563] RSP: 0018:ffffb670001d7e08 EFLAGS: 00010246 [ 182.609007] RAX: ffffffff92349e8d RBX: 0000000000000000 RCX: ffff99b1011e5870 [ 182.609595] RDX: 0000000000000000 RSI: ffffffff92268cf0 RDI: ffffffff92914d10 [ 182.610283] RBP: ffff99b1011e5870 R08: 0000000000000000 R09: ffff99b101b06c80 [ 182.610847] R10: ffff99b10139a808 R11: fefefefefefefeff R12: 0000000000000000 [ 182.611414] R13: ffffffff90cf74d0 R14: 0000000000000000 R15: ffff99b1011e5800 [ 182.612009] FS: 0000000000000000(0000) GS:ffff99b1eaaee000(0000) knlGS:0000000000000000 [ 182.612670] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 182.613146] CR2: 00000000005c631c CR3: 00000000013ee000 CR4: 00000000000006f0 [ 182.613722] Call Trace: [ 182.613946] <TASK> [ 182.614130] __iterate_supers+0x128/0x150 [ 182.614463] do_thaw_all+0x1b/0x30 [ 182.614759] process_scheduled_works+0xbb/0x3f0 [ 182.615150] ? __pfx_worker_thread+0x10/0x10 [ 182.615499] worker_thread+0x129/0x270 [ 182.615816] ? __pfx_worker_thread+0x10/0x10 [ 182.616201] kthread+0xe2/0x120 [ 182.616469] ? __pfx_kthread+0x10/0x10 [ 182.616792] ret_from_fork+0x15b/0x240 [ 182.617115] ? __pfx_kthread+0x10/0x10 [ 182.617426] ret_from_fork_asm+0x1a/0x30 [ 182.617761] </TASK> [ 182.617968] ---[ end trace 0000000000000000 ]--- [ 182.618412] Emergency Thaw complete Fix this by switching to SUPER_ITER_UNLOCKED and acquiring s_umount in the callback via super_lock_excl() before calling thaw_super_locked(). This matches the locking pattern expected by thaw_super_locked() and eliminates the double unlock. While at it, remove the dead 'return;' at the end of do_thaw_all_callback(). Fixes: 2992476 ("super: use a common iterator (Part 1)") Cc: stable@vger.kernel.org Signed-off-by: Chen Changcheng <chenchangcheng@kylinos.cn> Link: https://patch.msgid.link/20260721064140.152305-1-chenchangcheng@kylinos.cn Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
No description provided.