SLAB_TYPESAFE_BY_RCU(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’… SLAB_TYPESAFE_BY_RCU(9) πŸ’…

okay bestie, sit down, we're reading a kernel API manual page (yes, from the Kernel API Manual, we're fancy now) and this one is literally a WARNING page. Like, the name section is literally "WARNING READ THIS!" β€” so read it, fr fr. 🫢


✨ SYNOPSIS ✨

SLAB_TYPESAFE_BY_RCU

that's it. that's the whole synopsis. iconic minimalism. πŸŽ€


🌸 DESCRIPTION 🌸

okay so the vibe here: this flag delays freeing the SLAB page by a grace period. but β€” and this is the part people get wrong 😭 β€” it does _NOT_ delay object freeing. none. zero. nada.

so what that means is: if you do kmem_cache_free, that memory location is free to be reused at any time. like, immediately. so it's totally possible to see another object sitting there in the same RCU grace period. yes, in the SAME grace period. not a drill. πŸ’€

this feature only guarantees one thing: that the memory location backing the object stays valid. that's it. that's the whole promise. the trick to actually using this without setting your kernel on fire is relying on an independent object validation pass. something like this πŸ‘‡

there's a lone : hanging out right before the snippet in the original page and we're keeping it because it's part of the lore:

:

 begin:
  rcu_read_lock;
  obj = lockless_lookup(key);
  if (obj) {
    if (!try_get_ref(obj)) // might fail for free objects
      rcu_read_unlock;
      goto begin;

    if (obj->key != key) { // not the object we expected
      put_ref(obj);
      rcu_read_unlock;
      goto begin;
    }
  }
 rcu_read_unlock;

see how it loops back? that's the whole strategy. try_get_ref might fail for free objects, and even when it works the obj->key might not match β€” meaning it's not the object we expected β€” so you put_ref(obj), drop the rcu_read_unlock, and goto begin to try again. slay. πŸ”

this is useful when we need to approach a kernel structure obliquely β€” like, from its address obtained without the usual locking. we can lock the structure to stabilize it and check it's still at the given address, but ONLY if we can be sure the memory hasn't meanwhile been reused for some other kind of object. because if it has? our subsystem's lock might corrupt it. not cute. 🚫

so the move is: rcu_read_lock before reading the address, then rcu_read_unlock after taking the spinlock within the structure expected at that address. order matters, bestie. ⭐

timing check, no cap: object identity check has to be done _after_ acquiring a reference, so the user has to ensure proper ordering for loads. and similarly? when initializing objects allocated with SLAB_TYPESAFE_BY_RCU, the newly allocated object has to be fully initialized _before_ its refcount gets initialized, and proper ordering for stores is required too. this is the part where you go "wait what" and then re-read it. πŸ™ˆ

good news: refcount_{add|inc}_not_zero_acquire and refcount_set_release are literally designed with the proper fences required for reference counting objects allocated with SLAB_TYPESAFE_BY_RCU. so use those, they're the main characters here. πŸ‘‘

also β€” big one β€” it is not possible to acquire a lock within a structure allocated with SLAB_TYPESAFE_BY_RCU without first acquiring a reference as described above. why? because SLAB_TYPESAFE_BY_RCU pages are not zeroed before being given to the slab, which means any locks must be initialized after each and every kmem_struct_alloc. every single one. πŸ”₯

alternatively (and this is the elegant route πŸ’…): make the ctor passed to kmem_cache_create initialize the locks at page-allocation time, exactly like it's done in __i915_request_ctor, sighand_ctor, and anon_vma_ctor. such a ctor permits readers to safely acquire those ctor-initialized locks under rcu_read_lock protection. chef's kiss. 🧚

πŸ•°οΈ lore drop: SLAB_TYPESAFE_BY_RCU was originally named SLAB_DESTROY_BY_RCU. yes, it got a glow-up and a rebrand. we love a rename era.

πŸ¦‹ SEE ALSO πŸ¦‹

kernel file ./include/linux/slab.h and also, in no particular order because they're all here:

that's the whole reading list, go study, iykyk πŸ“šβœ¨


aaaand that's the page!! πŸ’– this one lives in ./include/linux, dated October 2026, and it's filed under SLAB_TYPESAFE_BY_RCU(9) β€” so if you forget it, that's where to find it. mwah, go forth and validate your objects properly πŸ«ΆπŸŒˆπŸ“

πŸ“¦ where this page comes from