1 From foo@baz Sun Jun 17 12:07:34 CEST 2018
2 From: Waiman Long <longman@redhat.com>
3 Date: Tue, 15 May 2018 17:49:51 -0400
4 Subject: locking/percpu-rwsem: Annotate rwsem ownership transfer by setting RWSEM_OWNER_UNKNOWN
6 From: Waiman Long <longman@redhat.com>
8 [ Upstream commit 5a817641f68a6399a5fac8b7d2da67a73698ffed ]
10 The filesystem freezing code needs to transfer ownership of a rwsem
11 embedded in a percpu-rwsem from the task that does the freezing to
12 another one that does the thawing by calling percpu_rwsem_release()
13 after freezing and percpu_rwsem_acquire() before thawing.
15 However, the new rwsem debug code runs afoul with this scheme by warning
16 that the task that releases the rwsem isn't the one that acquires it,
17 as reported by Amir Goldstein:
19 DEBUG_LOCKS_WARN_ON(sem->owner != get_current())
20 WARNING: CPU: 1 PID: 1401 at /home/amir/build/src/linux/kernel/locking/rwsem.c:133 up_write+0x59/0x79
23 percpu_up_write+0x1f/0x28
24 thaw_super_locked+0xdf/0x120
25 do_vfs_ioctl+0x270/0x5f1
27 __x64_sys_ioctl+0x16/0x19
28 do_syscall_64+0x5d/0x167
29 entry_SYSCALL_64_after_hwframe+0x49/0xbe
31 To work properly with the rwsem debug code, we need to annotate that the
32 rwsem ownership is unknown during the tranfer period until a brave soul
33 comes forward to acquire the ownership. During that period, optimistic
34 spinning will be disabled.
36 Reported-by: Amir Goldstein <amir73il@gmail.com>
37 Tested-by: Amir Goldstein <amir73il@gmail.com>
38 Signed-off-by: Waiman Long <longman@redhat.com>
39 Acked-by: Peter Zijlstra <peterz@infradead.org>
40 Cc: Andrew Morton <akpm@linux-foundation.org>
41 Cc: Davidlohr Bueso <dave@stgolabs.net>
42 Cc: Jan Kara <jack@suse.cz>
43 Cc: Linus Torvalds <torvalds@linux-foundation.org>
44 Cc: Matthew Wilcox <willy@infradead.org>
45 Cc: Oleg Nesterov <oleg@redhat.com>
46 Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
47 Cc: Theodore Y. Ts'o <tytso@mit.edu>
48 Cc: Thomas Gleixner <tglx@linutronix.de>
49 Cc: Will Deacon <will.deacon@arm.com>
50 Cc: linux-fsdevel@vger.kernel.org
51 Link: http://lkml.kernel.org/r/1526420991-21213-3-git-send-email-longman@redhat.com
52 Signed-off-by: Ingo Molnar <mingo@kernel.org>
53 Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
54 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
56 include/linux/percpu-rwsem.h | 6 +++++-
57 include/linux/rwsem.h | 6 ++++++
58 kernel/locking/rwsem-xadd.c | 2 ++
59 3 files changed, 13 insertions(+), 1 deletion(-)
61 --- a/include/linux/percpu-rwsem.h
62 +++ b/include/linux/percpu-rwsem.h
63 @@ -133,7 +133,7 @@ static inline void percpu_rwsem_release(
64 lock_release(&sem->rw_sem.dep_map, 1, ip);
65 #ifdef CONFIG_RWSEM_SPIN_ON_OWNER
67 - sem->rw_sem.owner = NULL;
68 + sem->rw_sem.owner = RWSEM_OWNER_UNKNOWN;
72 @@ -141,6 +141,10 @@ static inline void percpu_rwsem_acquire(
73 bool read, unsigned long ip)
75 lock_acquire(&sem->rw_sem.dep_map, 0, 1, read, 1, NULL, ip);
76 +#ifdef CONFIG_RWSEM_SPIN_ON_OWNER
78 + sem->rw_sem.owner = current;
83 --- a/include/linux/rwsem.h
84 +++ b/include/linux/rwsem.h
85 @@ -44,6 +44,12 @@ struct rw_semaphore {
90 + * Setting bit 0 of the owner field with other non-zero bits will indicate
91 + * that the rwsem is writer-owned with an unknown owner.
93 +#define RWSEM_OWNER_UNKNOWN ((struct task_struct *)-1L)
95 extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
96 extern struct rw_semaphore *rwsem_down_read_failed_killable(struct rw_semaphore *sem);
97 extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
98 --- a/kernel/locking/rwsem-xadd.c
99 +++ b/kernel/locking/rwsem-xadd.c
100 @@ -352,6 +352,8 @@ static inline bool rwsem_can_spin_on_own
101 struct task_struct *owner;
104 + BUILD_BUG_ON(!rwsem_has_anonymous_owner(RWSEM_OWNER_UNKNOWN));