Following up on D23469.
refcount(9) as implemented right now has the following properties:
- always operates on an int type, allowing consumers to misuse the field by accident. this is fixable by requiring a struct to be passed instead.
- supports waking up sleepers, implemented by adding a dedicated flag bit
- performs range checks at runtime, making sure total count wont flip the bit (and previous would was just checking for overflow)
VFS was using it for the 2 vnode reference counts before the range check or flag bits were introduced, while sometimes mixing in custom fiddling without said routines. With introduction of flags said mixed behavior turned into a bug which can result in use-after-free (that is, not-gating update can push the count to a state where the top bit is set with it masked the count is just 1; then refcount_release will conclude the object is to be freed and there are waiters to wake up).
Pushing VFS completely out of recount(9) as implemented right now has the following benefits:
- not braching on stuff we don't need for this usecase
- custom assertion support -- that is, should anything go wrong we can always end up dumping the vnode with vn_printf instead of just stating that the count has invalid value
To that end, I implemented an API which is a simple wrapper around atomics.
Properties:
- int and long sizes
- some degree of type safety by providing refcntint_t and refcntlong_t (i.e., no accidental misuse)
- custom callback for assertion failures
- the FILE, LINE, func triple is gathered *before* going into an inline routine. this means when the assertion fires we get the actual user and not the inline routine itself
sys/_refcount.h header was added to avoid dependency issues with zfs. adding refcount.h to vnode.h causes significant compilation problems.
This requires more testing, but is roughly what I have in mind.