Commit 071d8e4c authored by Michal Koutný's avatar Michal Koutný Committed by Greg Kroah-Hartman
Browse files

kernfs: Relax constraint in draining guard

The active reference lifecycle provides the break/unbreak mechanism but
the active reference is not truly active after unbreak -- callers don't
use it afterwards but it's important for proper pairing of kn->active
counting. Assuming this mechanism is in place, the WARN check in
kernfs_should_drain_open_files() is too sensitive -- it may transiently
catch those (rightful) callers between
kernfs_unbreak_active_protection() and kernfs_put_active() as found out by Chen
Ridong:

	kernfs_remove_by_name_ns	kernfs_get_active // active=1
	__kernfs_remove					  // active=0x80000002
	kernfs_drain			...
	wait_event
	//waiting (active == 0x80000001)
					kernfs_break_active_protection
					// active = 0x80000001
	// continue
					kernfs_unbreak_active_protection
					// active = 0x80000002
	...
	kernfs_should_drain_open_files
	// warning occurs
					kernfs_put_active

To avoid the false positives (mind panic_on_warn) remove the check altogether.
(This is meant as quick fix, I think active reference break/unbreak may be
simplified with larger rework.)

Fixes: bdb2fd7f ("kernfs: Skip kernfs_drain_open_files() more aggressively")
Link: https://lore.kernel.org/r/kmmrseckjctb4gxcx2rdminrjnq2b4ipf7562nvfd432ld5v5m@2byj5eedkb2o/



Cc: Chen Ridong <chenridong@huawei.com>
Signed-off-by: default avatarMichal Koutný <mkoutny@suse.com>
Acked-by: default avatarTejun Heo <tj@kernel.org>
Link: https://lore.kernel.org/r/20250505121201.879823-1-mkoutny@suse.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 28258282
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -1582,8 +1582,9 @@ void kernfs_break_active_protection(struct kernfs_node *kn)
 * invoked before finishing the kernfs operation.  Note that while this
 * function restores the active reference, it doesn't and can't actually
 * restore the active protection - @kn may already or be in the process of
 * being removed.  Once kernfs_break_active_protection() is invoked, that
 * protection is irreversibly gone for the kernfs operation instance.
 * being drained and removed.  Once kernfs_break_active_protection() is
 * invoked, that protection is irreversibly gone for the kernfs operation
 * instance.
 *
 * While this function may be called at any point after
 * kernfs_break_active_protection() is invoked, its most useful location
+2 −1
Original line number Diff line number Diff line
@@ -778,8 +778,9 @@ bool kernfs_should_drain_open_files(struct kernfs_node *kn)
	/*
	 * @kn being deactivated guarantees that @kn->attr.open can't change
	 * beneath us making the lockless test below safe.
	 * Callers post kernfs_unbreak_active_protection may be counted in
	 * kn->active by now, do not WARN_ON because of them.
	 */
	WARN_ON_ONCE(atomic_read(&kn->active) != KN_DEACTIVATED_BIAS);

	rcu_read_lock();
	on = rcu_dereference(kn->attr.open);