Skip to content

Commit 4a57d6b

Browse files
minchanktorvalds
authored andcommitted
locking/rwlocks: introduce write_lock_nested
In preparation for converting bit_spin_lock to rwlock in zsmalloc so that multiple writers of zspages can run at the same time but those zspages are supposed to be different zspage instance. Thus, it's not deadlock. This patch adds write_lock_nested to support the case for LOCKDEP. [[email protected]: fix write_lock_nested for RT] Link: https://lkml.kernel.org/r/[email protected] [[email protected]: fixup write_lock_nested() implementation] Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Minchan Kim <[email protected]> Signed-off-by: Sebastian Andrzej Siewior <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Acked-by: Sebastian Andrzej Siewior <[email protected]> Tested-by: Sebastian Andrzej Siewior <[email protected]> Cc: Mike Galbraith <[email protected]> Cc: Sergey Senozhatsky <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Naresh Kamboju <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent c4549b8 commit 4a57d6b

File tree

6 files changed

+47
-0
lines changed

6 files changed

+47
-0
lines changed

include/linux/rwlock.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ do { \
5555
#define write_lock(lock) _raw_write_lock(lock)
5656
#define read_lock(lock) _raw_read_lock(lock)
5757

58+
#ifdef CONFIG_DEBUG_LOCK_ALLOC
59+
#define write_lock_nested(lock, subclass) _raw_write_lock_nested(lock, subclass)
60+
#else
61+
#define write_lock_nested(lock, subclass) _raw_write_lock(lock)
62+
#endif
63+
5864
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
5965

6066
#define read_lock_irqsave(lock, flags) \

include/linux/rwlock_api_smp.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
void __lockfunc _raw_read_lock(rwlock_t *lock) __acquires(lock);
1919
void __lockfunc _raw_write_lock(rwlock_t *lock) __acquires(lock);
20+
void __lockfunc _raw_write_lock_nested(rwlock_t *lock, int subclass) __acquires(lock);
2021
void __lockfunc _raw_read_lock_bh(rwlock_t *lock) __acquires(lock);
2122
void __lockfunc _raw_write_lock_bh(rwlock_t *lock) __acquires(lock);
2223
void __lockfunc _raw_read_lock_irq(rwlock_t *lock) __acquires(lock);
@@ -209,6 +210,13 @@ static inline void __raw_write_lock(rwlock_t *lock)
209210
LOCK_CONTENDED(lock, do_raw_write_trylock, do_raw_write_lock);
210211
}
211212

213+
static inline void __raw_write_lock_nested(rwlock_t *lock, int subclass)
214+
{
215+
preempt_disable();
216+
rwlock_acquire(&lock->dep_map, subclass, 0, _RET_IP_);
217+
LOCK_CONTENDED(lock, do_raw_write_trylock, do_raw_write_lock);
218+
}
219+
212220
#endif /* !CONFIG_GENERIC_LOCKBREAK || CONFIG_DEBUG_LOCK_ALLOC */
213221

214222
static inline void __raw_write_unlock(rwlock_t *lock)

include/linux/rwlock_rt.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ extern void rt_read_lock(rwlock_t *rwlock);
2828
extern int rt_read_trylock(rwlock_t *rwlock);
2929
extern void rt_read_unlock(rwlock_t *rwlock);
3030
extern void rt_write_lock(rwlock_t *rwlock);
31+
extern void rt_write_lock_nested(rwlock_t *rwlock, int subclass);
3132
extern int rt_write_trylock(rwlock_t *rwlock);
3233
extern void rt_write_unlock(rwlock_t *rwlock);
3334

@@ -83,6 +84,15 @@ static __always_inline void write_lock(rwlock_t *rwlock)
8384
rt_write_lock(rwlock);
8485
}
8586

87+
#ifdef CONFIG_DEBUG_LOCK_ALLOC
88+
static __always_inline void write_lock_nested(rwlock_t *rwlock, int subclass)
89+
{
90+
rt_write_lock_nested(rwlock, subclass);
91+
}
92+
#else
93+
#define write_lock_nested(lock, subclass) rt_write_lock(((void)(subclass), (lock)))
94+
#endif
95+
8696
static __always_inline void write_lock_bh(rwlock_t *rwlock)
8797
{
8898
local_bh_disable();

include/linux/spinlock_api_up.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
#define _raw_spin_lock_nested(lock, subclass) __LOCK(lock)
6060
#define _raw_read_lock(lock) __LOCK(lock)
6161
#define _raw_write_lock(lock) __LOCK(lock)
62+
#define _raw_write_lock_nested(lock, subclass) __LOCK(lock)
6263
#define _raw_spin_lock_bh(lock) __LOCK_BH(lock)
6364
#define _raw_read_lock_bh(lock) __LOCK_BH(lock)
6465
#define _raw_write_lock_bh(lock) __LOCK_BH(lock)

kernel/locking/spinlock.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,16 @@ void __lockfunc _raw_write_lock(rwlock_t *lock)
300300
__raw_write_lock(lock);
301301
}
302302
EXPORT_SYMBOL(_raw_write_lock);
303+
304+
#ifndef CONFIG_DEBUG_LOCK_ALLOC
305+
#define __raw_write_lock_nested(lock, subclass) __raw_write_lock(((void)(subclass), (lock)))
306+
#endif
307+
308+
void __lockfunc _raw_write_lock_nested(rwlock_t *lock, int subclass)
309+
{
310+
__raw_write_lock_nested(lock, subclass);
311+
}
312+
EXPORT_SYMBOL(_raw_write_lock_nested);
303313
#endif
304314

305315
#ifndef CONFIG_INLINE_WRITE_LOCK_IRQSAVE

kernel/locking/spinlock_rt.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,18 @@ void __sched rt_write_lock(rwlock_t *rwlock)
239239
}
240240
EXPORT_SYMBOL(rt_write_lock);
241241

242+
#ifdef CONFIG_DEBUG_LOCK_ALLOC
243+
void __sched rt_write_lock_nested(rwlock_t *rwlock, int subclass)
244+
{
245+
rtlock_might_resched();
246+
rwlock_acquire(&rwlock->dep_map, subclass, 0, _RET_IP_);
247+
rwbase_write_lock(&rwlock->rwbase, TASK_RTLOCK_WAIT);
248+
rcu_read_lock();
249+
migrate_disable();
250+
}
251+
EXPORT_SYMBOL(rt_write_lock_nested);
252+
#endif
253+
242254
void __sched rt_read_unlock(rwlock_t *rwlock)
243255
{
244256
rwlock_release(&rwlock->dep_map, _RET_IP_);

0 commit comments

Comments
 (0)