aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/locking.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/locking.c')
-rw-r--r--fs/btrfs/locking.c42
1 files changed, 19 insertions, 23 deletions
diff --git a/fs/btrfs/locking.c b/fs/btrfs/locking.c
index 9ebe9385129b..1c36e5cd8f55 100644
--- a/fs/btrfs/locking.c
+++ b/fs/btrfs/locking.c
@@ -25,21 +25,10 @@
25#include "extent_io.h" 25#include "extent_io.h"
26#include "locking.h" 26#include "locking.h"
27 27
28/*
29 * btrfs_header_level() isn't free, so don't call it when lockdep isn't
30 * on
31 */
32#ifdef CONFIG_DEBUG_LOCK_ALLOC
33static inline void spin_nested(struct extent_buffer *eb)
34{
35 spin_lock_nested(&eb->lock, BTRFS_MAX_LEVEL - btrfs_header_level(eb));
36}
37#else
38static inline void spin_nested(struct extent_buffer *eb) 28static inline void spin_nested(struct extent_buffer *eb)
39{ 29{
40 spin_lock(&eb->lock); 30 spin_lock(&eb->lock);
41} 31}
42#endif
43 32
44/* 33/*
45 * Setting a lock to blocking will drop the spinlock and set the 34 * Setting a lock to blocking will drop the spinlock and set the
@@ -71,8 +60,8 @@ void btrfs_clear_lock_blocking(struct extent_buffer *eb)
71 60
72/* 61/*
73 * unfortunately, many of the places that currently set a lock to blocking 62 * unfortunately, many of the places that currently set a lock to blocking
74 * don't end up blocking for every long, and often they don't block 63 * don't end up blocking for very long, and often they don't block
75 * at all. For a dbench 50 run, if we don't spin one the blocking bit 64 * at all. For a dbench 50 run, if we don't spin on the blocking bit
76 * at all, the context switch rate can jump up to 400,000/sec or more. 65 * at all, the context switch rate can jump up to 400,000/sec or more.
77 * 66 *
78 * So, we're still stuck with this crummy spin on the blocking bit, 67 * So, we're still stuck with this crummy spin on the blocking bit,
@@ -82,12 +71,13 @@ void btrfs_clear_lock_blocking(struct extent_buffer *eb)
82static int btrfs_spin_on_block(struct extent_buffer *eb) 71static int btrfs_spin_on_block(struct extent_buffer *eb)
83{ 72{
84 int i; 73 int i;
74
85 for (i = 0; i < 512; i++) { 75 for (i = 0; i < 512; i++) {
86 cpu_relax();
87 if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags)) 76 if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags))
88 return 1; 77 return 1;
89 if (need_resched()) 78 if (need_resched())
90 break; 79 break;
80 cpu_relax();
91 } 81 }
92 return 0; 82 return 0;
93} 83}
@@ -106,13 +96,15 @@ int btrfs_try_spin_lock(struct extent_buffer *eb)
106{ 96{
107 int i; 97 int i;
108 98
109 spin_nested(eb); 99 if (btrfs_spin_on_block(eb)) {
110 if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags)) 100 spin_nested(eb);
111 return 1; 101 if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags))
112 spin_unlock(&eb->lock); 102 return 1;
113 103 spin_unlock(&eb->lock);
104 }
114 /* spin for a bit on the BLOCKING flag */ 105 /* spin for a bit on the BLOCKING flag */
115 for (i = 0; i < 2; i++) { 106 for (i = 0; i < 2; i++) {
107 cpu_relax();
116 if (!btrfs_spin_on_block(eb)) 108 if (!btrfs_spin_on_block(eb))
117 break; 109 break;
118 110
@@ -159,6 +151,9 @@ int btrfs_tree_lock(struct extent_buffer *eb)
159 DEFINE_WAIT(wait); 151 DEFINE_WAIT(wait);
160 wait.func = btrfs_wake_function; 152 wait.func = btrfs_wake_function;
161 153
154 if (!btrfs_spin_on_block(eb))
155 goto sleep;
156
162 while(1) { 157 while(1) {
163 spin_nested(eb); 158 spin_nested(eb);
164 159
@@ -176,9 +171,10 @@ int btrfs_tree_lock(struct extent_buffer *eb)
176 * spin for a bit, and if the blocking flag goes away, 171 * spin for a bit, and if the blocking flag goes away,
177 * loop around 172 * loop around
178 */ 173 */
174 cpu_relax();
179 if (btrfs_spin_on_block(eb)) 175 if (btrfs_spin_on_block(eb))
180 continue; 176 continue;
181 177sleep:
182 prepare_to_wait_exclusive(&eb->lock_wq, &wait, 178 prepare_to_wait_exclusive(&eb->lock_wq, &wait,
183 TASK_UNINTERRUPTIBLE); 179 TASK_UNINTERRUPTIBLE);
184 180
@@ -231,8 +227,8 @@ int btrfs_tree_unlock(struct extent_buffer *eb)
231 return 0; 227 return 0;
232} 228}
233 229
234int btrfs_tree_locked(struct extent_buffer *eb) 230void btrfs_assert_tree_locked(struct extent_buffer *eb)
235{ 231{
236 return test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags) || 232 if (!test_bit(EXTENT_BUFFER_BLOCKING, &eb->bflags))
237 spin_is_locked(&eb->lock); 233 assert_spin_locked(&eb->lock);
238} 234}