Whamcloud - gitweb
LU-15156 kernel: back port patch for rwsem issue
[fs/lustre-release.git] / lustre / kernel_patches / patches / rwsem-remove-wakeup-optimization.patch
1 From 5c1ec49b60cdb31e51010f8a647f3189b774bddf Mon Sep 17 00:00:00 2001
2 From: Waiman Long <longman@redhat.com>
3 Date: Mon, 20 May 2019 16:59:01 -0400
4 Subject: [PATCH] locking/rwsem: Remove rwsem_wake() wakeup optimization
5
6 After the following commit:
7
8   59aabfc7e959 ("locking/rwsem: Reduce spinlock contention in wakeup after up_read()/up_write()")
9
10 the rwsem_wake() forgoes doing a wakeup if the wait_lock cannot be directly
11 acquired and an optimistic spinning locker is present.  This can help performance
12 by avoiding spinning on the wait_lock when it is contended.
13
14 With the later commit:
15
16   133e89ef5ef3 ("locking/rwsem: Enable lockless waiter wakeup(s)")
17
18 the performance advantage of the above optimization diminishes as the average
19 wait_lock hold time become much shorter.
20
21 With a later patch that supports rwsem lock handoff, we can no
22 longer relies on the fact that the presence of an optimistic spinning
23 locker will ensure that the lock will be acquired by a task soon and
24 rwsem_wake() will be called later on to wake up waiters. This can lead
25 to missed wakeup and application hang.
26
27 So the original 59aabfc7e959 commit has to be reverted.
28
29 Signed-off-by: Waiman Long <longman@redhat.com>
30 Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
31 Cc: Borislav Petkov <bp@alien8.de>
32 Cc: Davidlohr Bueso <dave@stgolabs.net>
33 Cc: H. Peter Anvin <hpa@zytor.com>
34 Cc: Linus Torvalds <torvalds@linux-foundation.org>
35 Cc: Peter Zijlstra <peterz@infradead.org>
36 Cc: Thomas Gleixner <tglx@linutronix.de>
37 Cc: Tim Chen <tim.c.chen@linux.intel.com>
38 Cc: Will Deacon <will.deacon@arm.com>
39 Cc: huang ying <huang.ying.caritas@gmail.com>
40 Link: https://lkml.kernel.org/r/20190520205918.22251-3-longman@redhat.com
41 Signed-off-by: Ingo Molnar <mingo@kernel.org>
42 ---
43  kernel/locking/rwsem-xadd.c | 72 -------------------------------------
44  1 file changed, 72 deletions(-)
45
46 diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c
47 index c0500679fd2f..3083fdf50447 100644
48 --- a/lib/rwsem.c
49 +++ b/lib/rwsem.c
50 @@ -411,25 +411,11 @@ static bool rwsem_optimistic_spin(struct rw_semaphore *sem)
51         preempt_enable();
52         return taken;
53  }
54 -
55 -/*
56 - * Return true if the rwsem has active spinner
57 - */
58 -static inline bool rwsem_has_spinner(struct rw_semaphore *sem)
59 -{
60 -       return osq_is_locked(&sem->osq);
61 -}
62 -
63  #else
64  static bool rwsem_optimistic_spin(struct rw_semaphore *sem)
65  {
66         return false;
67  }
68 -
69 -static inline bool rwsem_has_spinner(struct rw_semaphore *sem)
70 -{
71 -       return false;
72 -}
73  #endif
74  
75  /*
76 @@ -651,38 +637,7 @@ struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem)
77         unsigned long flags;
78         WAKE_Q(wake_q);
79  
80 -       /*
81 -        * If a spinner is present, it is not necessary to do the wakeup.
82 -        * Try to do wakeup only if the trylock succeeds to minimize
83 -        * spinlock contention which may introduce too much delay in the
84 -        * unlock operation.
85 -        *
86 -        *    spinning writer           up_write/up_read caller
87 -        *    ---------------           -----------------------
88 -        * [S]   osq_unlock()           [L]   osq
89 -        *       MB                           RMB
90 -        * [RmW] rwsem_try_write_lock() [RmW] spin_trylock(wait_lock)
91 -        *
92 -        * Here, it is important to make sure that there won't be a missed
93 -        * wakeup while the rwsem is free and the only spinning writer goes
94 -        * to sleep without taking the rwsem. Even when the spinning writer
95 -        * is just going to break out of the waiting loop, it will still do
96 -        * a trylock in rwsem_down_write_failed() before sleeping. IOW, if
97 -        * rwsem_has_spinner() is true, it will guarantee at least one
98 -        * trylock attempt on the rwsem later on.
99 -        */
100 -       if (rwsem_has_spinner(sem)) {
101 -               /*
102 -                * The smp_rmb() here is to make sure that the spinner
103 -                * state is consulted before reading the wait_lock.
104 -                */
105 -               smp_rmb();
106 -               if (!raw_spin_trylock_irqsave(&sem->wait_lock, flags))
107 -                       return sem;
108 -               goto locked;
109 -       }
110         raw_spin_lock_irqsave(&sem->wait_lock, flags);
111 -locked:
112  
113         /* do nothing if list empty */
114         if (!slist_empty(&sem->wait_list))
115 -- 
116 2.17.2 (Apple Git-113)
117