file_ref_t: allow for valid race
The following race exists when putting the last reference to a file:
CPU1 CPU2
file_ref_put()
// last reference
// => count goes negative/FILE_REF_NOREF
atomic_long_add_negative_release(-1, &ref->refcnt)
-> __file_ref_put()
file_ref_get()
// goes back from negative/FILE_REF_NOREF to 0
atomic_long_add_negative(1, &ref->refcnt)
// manages to put last reference
// and set FILE_REF_DEAD
file_ref_put()
// Sees cnt > FILE_REF_RELEASED
// and splats with
// "imbalanced put on file reference count"
cnt = atomic_long_read(&ref->refcnt);
This race is benign and the problem is the atomic_long_read(). Instead
of performing a separate read, use atomic_long_dec_return() and pass the
value to __file_ref_put(). Thanks to Linus for pointing out that braino.
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Reported-by: kernel test robot <oliver.sang@intel.com>
Closes: https://lore.kernel.org/oe-lkp/202410151043.5d224a27-oliver.sang@intel.com
Closes: https://lore.kernel.org/all/202410151611.f4cd71f2-oliver.sang@intel.com
Signed-off-by: Christian Brauner <brauner@kernel.org>
2 files changed