Compare commits

...

2 Commits

Author SHA1 Message Date
Auke Kok
d63b608658 Use spin_lock_bh on recinf->lock to fix softirq deadlock
timer_callback() runs in softirq context and acquires recinf->lock,
but the process-context callers (scoutfs_recov_prepare, _begin,
_finish, _is_pending, _next_pending, _shutdown) were taking the
same lock with plain spin_lock(), leaving softirqs enabled. Found
by Lockdep:

```
	================================
	WARNING: inconsistent lock state
	5.14.0-427.35.1.el9_4.x86_64+debug #1 Tainted: G           OE     -------  ---
	--------------------------------
	inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage.
	swapper/2/0 [HC0[0]:SC1[1]:HE1:SE0] takes:
	ffff88813cdd9c20 (&recinf->lock){+.?.}-{2:2}, at: timer_callback+0x26/0x380 [scoutfs]
	{SOFTIRQ-ON-W} state was registered at:
	  __lock_acquire+0x7d0/0x1900
	  lock_acquire+0x1da/0x640
	  _raw_spin_lock+0x34/0x80
	  scoutfs_recov_finish+0x80/0x830 [scoutfs]
	  server_greeting+0x244/0xe60 [scoutfs]
	  scoutfs_net_proc_worker+0x28a/0xce0 [scoutfs]
	  recv_one_message+0x7e3/0xd10 [scoutfs]
	  scoutfs_net_recv_worker+0x441/0xe00 [scoutfs]
	  process_one_work+0x8e5/0x1530
	  worker_thread+0x598/0xf70
	  kthread+0x2a4/0x350
	  ret_from_fork+0x29/0x50
	irq event stamp: 549813370
	hardirqs last  enabled at (549813370): [<ffffffffabe25cb4>] _raw_spin_unlock_irq+0x24/0x50
	hardirqs last disabled at (549813369): [<ffffffffabe2594e>] _raw_spin_lock_irq+0x5e/0x90
	softirqs last  enabled at (549813356): [<ffffffffabe28c91>] __do_softirq+0x621/0x9c2
	softirqs last disabled at (549813363): [<ffffffffa9a44665>] __irq_exit_rcu+0x185/0x230

	other info that might help us debug this:
	 Possible unsafe locking scenario:
	       CPU0
	       ----
	  lock(&recinf->lock);
	  <Interrupt>
	    lock(&recinf->lock);

	 *** DEADLOCK ***
```

Convert the six process-context sites to spin_lock_bh()/spin_unlock_bh().

Signed-off-by: Auke Kok <auke.kok@versity.com>
2026-05-12 11:26:55 -07:00
Zach Brown
fece0a9372 Merge pull request #310 from versity/zab/v1.31
v1.31 Release
2026-05-06 10:37:07 -07:00

View File

@@ -103,7 +103,7 @@ int scoutfs_recov_prepare(struct super_block *sb, u64 rid, int which)
if (!alloc)
return -ENOMEM;
spin_lock(&recinf->lock);
spin_lock_bh(&recinf->lock);
pend = lookup_pending(recinf, rid, SCOUTFS_RECOV_ALL);
if (pend) {
@@ -116,7 +116,7 @@ int scoutfs_recov_prepare(struct super_block *sb, u64 rid, int which)
list_sort(NULL, &recinf->pending, cmp_pending_rid);
}
spin_unlock(&recinf->lock);
spin_unlock_bh(&recinf->lock);
kfree(alloc);
return 0;
@@ -153,7 +153,7 @@ int scoutfs_recov_begin(struct super_block *sb, void (*timeout_fn)(struct super_
DECLARE_RECOV_INFO(sb, recinf);
int ret;
spin_lock(&recinf->lock);
spin_lock_bh(&recinf->lock);
recinf->timeout_fn = timeout_fn;
recinf->timer.expires = jiffies + msecs_to_jiffies(timeout_ms);
@@ -161,7 +161,7 @@ int scoutfs_recov_begin(struct super_block *sb, void (*timeout_fn)(struct super_
ret = recov_finished(recinf);
spin_unlock(&recinf->lock);
spin_unlock_bh(&recinf->lock);
if (ret > 0)
del_timer_sync(&recinf->timer);
@@ -183,7 +183,7 @@ int scoutfs_recov_finish(struct super_block *sb, u64 rid, int which)
struct recov_pending *pend;
int ret = 0;
spin_lock(&recinf->lock);
spin_lock_bh(&recinf->lock);
pend = lookup_pending(recinf, rid, which);
if (pend) {
@@ -196,7 +196,7 @@ int scoutfs_recov_finish(struct super_block *sb, u64 rid, int which)
}
}
spin_unlock(&recinf->lock);
spin_unlock_bh(&recinf->lock);
if (ret > 0)
del_timer_sync(&recinf->timer);
@@ -215,9 +215,9 @@ bool scoutfs_recov_is_pending(struct super_block *sb, u64 rid, int which)
DECLARE_RECOV_INFO(sb, recinf);
bool is_pending;
spin_lock(&recinf->lock);
spin_lock_bh(&recinf->lock);
is_pending = lookup_pending(recinf, rid, which) != NULL;
spin_unlock(&recinf->lock);
spin_unlock_bh(&recinf->lock);
return is_pending;
}
@@ -236,10 +236,10 @@ u64 scoutfs_recov_next_pending(struct super_block *sb, u64 rid, int which)
DECLARE_RECOV_INFO(sb, recinf);
struct recov_pending *pend;
spin_lock(&recinf->lock);
spin_lock_bh(&recinf->lock);
pend = next_pending(recinf, rid, which);
rid = pend ? pend->rid : 0;
spin_unlock(&recinf->lock);
spin_unlock_bh(&recinf->lock);
return rid;
}
@@ -257,10 +257,10 @@ void scoutfs_recov_shutdown(struct super_block *sb)
del_timer_sync(&recinf->timer);
spin_lock(&recinf->lock);
spin_lock_bh(&recinf->lock);
list_splice_init(&recinf->pending, &list);
recinf->timeout_fn = NULL;
spin_unlock(&recinf->lock);
spin_unlock_bh(&recinf->lock);
list_for_each_entry_safe(pend, tmp, &list, head) {
list_del(&pend->head);