Subject: rt/fs/dcache: Convert s_anon_lock to a raw spinlock
From: Mike Galbraith <mgalbraith@suse.de>
Date: Mon Jan 8 11:13:47 CET 2018
Patch-mainline: Never, SUSE/RT specific.
References: SLE12 Realtime Extension
We can't take a normal spinlock under write_seqlock(), as it
disables preemption. Convert s_anon_lock to a raw lock for RT.
"Improve fairness when locking the per-superblock s_anon list"
added this lock on Fri Jan 29 11:08:33 2016, how this did now
show up MUCH sooner than a YEAR later is a mystery.
[ 8252.753017] BUG: sleeping function called from invalid context at kernel/locking/rtmutex.c:996
[ 8252.753018] in_atomic(): 1, irqs_disabled(): 0, pid: 2884, name: nfsd
[ 8252.753022] Preemption disabled at:[<ffffffff8121ef4f>] __d_move+0x10f/0x5c0
[ 8252.753024]
[ 8252.753025] CPU: 6 PID: 2884 Comm: nfsd Tainted: G E N 4.4.104-SP3-rt #2
[ 8252.753026] Hardware name: MEDION MS-7848/MS-7848, BIOS M7848W08.20C 09/23/2013
[ 8252.753028] 0000000000000000 ffffffff81329e0e ffffffff81e0e540 ffff8803f763b0b8
[ 8252.753028] ffffffff8160c2bc ffff880002fc0780 ffffffff8121e048 0000000000000000
[ 8252.753031] ffff8803fa40bb08
[ 8252.753031] ffff880002fc07d8
[ 8252.753032] ffffffff8121ef6b ffff8803fa40baf8
[ 8252.753032] Call Trace:
[ 8252.753040] [<ffffffff81007009>] dump_trace+0x59/0x320
[ 8252.753043] [<ffffffff810073c3>] show_stack_log_lvl+0xf3/0x180
[ 8252.753044] [<ffffffff810081c1>] show_stack+0x21/0x40
[ 8252.753047] [<ffffffff81329e0e>] dump_stack+0x5c/0x7e
[ 8252.753050] [<ffffffff8160c2bc>] rt_spin_lock+0x1c/0x50
[ 8252.753052] [<ffffffff8121e048>] __d_drop+0x108/0x130
[ 8252.753054] [<ffffffff8121ef6b>] __d_move+0x12b/0x5c0
[ 8252.753056] [<ffffffff8121f68d>] d_splice_alias+0x23d/0x290
[ 8252.753069] [<ffffffffa010a4ed>] ext4_lookup+0xdd/0x130 [ext4]
[ 8252.753072] [<ffffffff81210bc9>] lookup_real+0x19/0x50
[ 8252.753074] [<ffffffff81210fbf>] __lookup_hash+0x2f/0x40
[ 8252.753076] [<ffffffff812126f5>] lookup_one_len+0xc5/0x120
[ 8252.753079] [<ffffffff81288889>] reconnect_path+0x109/0x2a0
[ 8252.753082] [<ffffffff81288b7d>] exportfs_decode_fh+0x10d/0x350
[ 8252.753090] [<ffffffffa05f862a>] fh_verify+0x2da/0x5a0 [nfsd]
[ 8252.753099] [<ffffffffa0607b20>] nfsd4_proc_compound+0x3b0/0x710 [nfsd]
[ 8252.753105] [<ffffffffa05f4f23>] nfsd_dispatch+0xc3/0x260 [nfsd]
[ 8252.753115] [<ffffffffa05830b8>] svc_process_common+0x418/0x6a0 [sunrpc]
[ 8252.753124] [<ffffffffa058343d>] svc_process+0xfd/0x230 [sunrpc]
[ 8252.753129] [<ffffffffa05f4964>] nfsd+0xf4/0x160 [nfsd]
[ 8252.753133] [<ffffffff8108fcf2>] kthread+0xd2/0xf0
[ 8252.753136] [<ffffffff8160cc5f>] ret_from_fork+0x3f/0x70
Signed-off-by: Mike Galbraith <mgalbraith@suse.de>
---
fs/dcache.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -113,7 +113,7 @@ static inline struct hlist_bl_head *d_ha
#define IN_LOOKUP_SHIFT 10
static struct hlist_bl_head in_lookup_hashtable[1 << IN_LOOKUP_SHIFT];
-static DEFINE_SPINLOCK(s_anon_lock);
+static DEFINE_RAW_SPINLOCK(s_anon_lock);
static inline struct hlist_bl_head *in_lookup_hash(const struct dentry *parent,
unsigned int hash)
@@ -483,12 +483,12 @@ static void ___d_drop(struct dentry *den
b = d_hash(dentry->d_name.hash);
if (b == &dentry->d_sb->s_anon)
- spin_lock(&s_anon_lock);
+ raw_spin_lock(&s_anon_lock);
hlist_bl_lock(b);
__hlist_bl_del(&dentry->d_hash);
hlist_bl_unlock(b);
if (b == &dentry->d_sb->s_anon)
- spin_unlock(&s_anon_lock);
+ raw_spin_unlock(&s_anon_lock);
/* After this call, in-progress rcu-walk path lookup will fail. */
write_seqcount_invalidate(&dentry->d_seq);
}
@@ -2018,11 +2018,11 @@ static struct dentry *__d_obtain_alias(s
spin_lock(&tmp->d_lock);
__d_set_inode_and_type(tmp, inode, add_flags);
hlist_add_head(&tmp->d_u.d_alias, &inode->i_dentry);
- spin_lock(&s_anon_lock);
+ raw_spin_lock(&s_anon_lock);
hlist_bl_lock(&tmp->d_sb->s_anon);
hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon);
hlist_bl_unlock(&tmp->d_sb->s_anon);
- spin_unlock(&s_anon_lock);
+ raw_spin_unlock(&s_anon_lock);
spin_unlock(&tmp->d_lock);
spin_unlock(&inode->i_lock);