diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-07-16 18:12:56 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-07-16 18:12:56 -0400 |
commit | a18f8775419d3df282dd83efdb51c5a64d092f31 (patch) | |
tree | 1e0abc5c1d30e8bc58dc23099017eca496992fd2 /fs/btrfs/locking.c | |
parent | 3eb514866f20c5eb74637279774b6d73b855480a (diff) | |
parent | e02d48eaaed77f6c36916a7aa65c451e1f9d9aab (diff) |
Merge tag 'for-5.3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs updates from David Sterba:
"Highlights:
- chunks that have been trimmed and unchanged since last mount are
tracked and skipped on repeated trims
- use hw assissed crc32c on more arches, speedups if native
instructions or optimized implementation is available
- the RAID56 incompat bit is automatically removed when the last
block group of that type is removed
Fixes:
- fsync fix for reflink on NODATACOW files that could lead to ENOSPC
- fix data loss after inode eviction, renaming it, and fsync it
- fix fsync not persisting dentry deletions due to inode evictions
- update ctime/mtime/iversion after hole punching
- fix compression type validation (reported by KASAN)
- send won't be allowed to start when relocation is in progress, this
can cause spurious errors or produce incorrect send stream
Core:
- new tracepoints for space update
- tree-checker: better check for end of extents for some tree items
- preparatory work for more checksum algorithms
- run delayed iput at unlink time and don't push the work to cleaner
thread where it's not properly throttled
- wrap block mapping to structures and helpers, base for further
refactoring
- split large files, part 1:
- space info handling
- block group reservations
- delayed refs
- delayed allocation
- other cleanups and refactoring"
* tag 'for-5.3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: (103 commits)
btrfs: fix memory leak of path on error return path
btrfs: move the subvolume reservation stuff out of extent-tree.c
btrfs: migrate the delalloc space stuff to it's own home
btrfs: migrate btrfs_trans_release_chunk_metadata
btrfs: migrate the delayed refs rsv code
btrfs: Evaluate io_tree in find_lock_delalloc_range()
btrfs: migrate the global_block_rsv helpers to block-rsv.c
btrfs: migrate the block-rsv code to block-rsv.c
btrfs: stop using block_rsv_release_bytes everywhere
btrfs: cleanup the target logic in __btrfs_block_rsv_release
btrfs: export __btrfs_block_rsv_release
btrfs: export btrfs_block_rsv_add_bytes
btrfs: move btrfs_block_rsv definitions into it's own header
btrfs: Simplify update of space_info in __reserve_metadata_bytes()
btrfs: unexport can_overcommit
btrfs: move reserve_metadata_bytes and supporting code to space-info.c
btrfs: move dump_space_info to space-info.c
btrfs: export block_rsv_use_bytes
btrfs: move btrfs_space_info_add_*_bytes to space-info.c
btrfs: move the space info update macro to space-info.h
...
Diffstat (limited to 'fs/btrfs/locking.c')
-rw-r--r-- | fs/btrfs/locking.c | 62 |
1 files changed, 28 insertions, 34 deletions
diff --git a/fs/btrfs/locking.c b/fs/btrfs/locking.c index 2f6c3c7851ed..98fccce4208c 100644 --- a/fs/btrfs/locking.c +++ b/fs/btrfs/locking.c | |||
@@ -15,19 +15,19 @@ | |||
15 | #ifdef CONFIG_BTRFS_DEBUG | 15 | #ifdef CONFIG_BTRFS_DEBUG |
16 | static void btrfs_assert_spinning_writers_get(struct extent_buffer *eb) | 16 | static void btrfs_assert_spinning_writers_get(struct extent_buffer *eb) |
17 | { | 17 | { |
18 | WARN_ON(atomic_read(&eb->spinning_writers)); | 18 | WARN_ON(eb->spinning_writers); |
19 | atomic_inc(&eb->spinning_writers); | 19 | eb->spinning_writers++; |
20 | } | 20 | } |
21 | 21 | ||
22 | static void btrfs_assert_spinning_writers_put(struct extent_buffer *eb) | 22 | static void btrfs_assert_spinning_writers_put(struct extent_buffer *eb) |
23 | { | 23 | { |
24 | WARN_ON(atomic_read(&eb->spinning_writers) != 1); | 24 | WARN_ON(eb->spinning_writers != 1); |
25 | atomic_dec(&eb->spinning_writers); | 25 | eb->spinning_writers--; |
26 | } | 26 | } |
27 | 27 | ||
28 | static void btrfs_assert_no_spinning_writers(struct extent_buffer *eb) | 28 | static void btrfs_assert_no_spinning_writers(struct extent_buffer *eb) |
29 | { | 29 | { |
30 | WARN_ON(atomic_read(&eb->spinning_writers)); | 30 | WARN_ON(eb->spinning_writers); |
31 | } | 31 | } |
32 | 32 | ||
33 | static void btrfs_assert_spinning_readers_get(struct extent_buffer *eb) | 33 | static void btrfs_assert_spinning_readers_get(struct extent_buffer *eb) |
@@ -58,17 +58,17 @@ static void btrfs_assert_tree_read_locked(struct extent_buffer *eb) | |||
58 | 58 | ||
59 | static void btrfs_assert_tree_write_locks_get(struct extent_buffer *eb) | 59 | static void btrfs_assert_tree_write_locks_get(struct extent_buffer *eb) |
60 | { | 60 | { |
61 | atomic_inc(&eb->write_locks); | 61 | eb->write_locks++; |
62 | } | 62 | } |
63 | 63 | ||
64 | static void btrfs_assert_tree_write_locks_put(struct extent_buffer *eb) | 64 | static void btrfs_assert_tree_write_locks_put(struct extent_buffer *eb) |
65 | { | 65 | { |
66 | atomic_dec(&eb->write_locks); | 66 | eb->write_locks--; |
67 | } | 67 | } |
68 | 68 | ||
69 | void btrfs_assert_tree_locked(struct extent_buffer *eb) | 69 | void btrfs_assert_tree_locked(struct extent_buffer *eb) |
70 | { | 70 | { |
71 | BUG_ON(!atomic_read(&eb->write_locks)); | 71 | BUG_ON(!eb->write_locks); |
72 | } | 72 | } |
73 | 73 | ||
74 | #else | 74 | #else |
@@ -111,10 +111,10 @@ void btrfs_set_lock_blocking_write(struct extent_buffer *eb) | |||
111 | */ | 111 | */ |
112 | if (eb->lock_nested && current->pid == eb->lock_owner) | 112 | if (eb->lock_nested && current->pid == eb->lock_owner) |
113 | return; | 113 | return; |
114 | if (atomic_read(&eb->blocking_writers) == 0) { | 114 | if (eb->blocking_writers == 0) { |
115 | btrfs_assert_spinning_writers_put(eb); | 115 | btrfs_assert_spinning_writers_put(eb); |
116 | btrfs_assert_tree_locked(eb); | 116 | btrfs_assert_tree_locked(eb); |
117 | atomic_inc(&eb->blocking_writers); | 117 | eb->blocking_writers++; |
118 | write_unlock(&eb->lock); | 118 | write_unlock(&eb->lock); |
119 | } | 119 | } |
120 | } | 120 | } |
@@ -148,12 +148,11 @@ void btrfs_clear_lock_blocking_write(struct extent_buffer *eb) | |||
148 | */ | 148 | */ |
149 | if (eb->lock_nested && current->pid == eb->lock_owner) | 149 | if (eb->lock_nested && current->pid == eb->lock_owner) |
150 | return; | 150 | return; |
151 | BUG_ON(atomic_read(&eb->blocking_writers) != 1); | ||
152 | write_lock(&eb->lock); | 151 | write_lock(&eb->lock); |
152 | BUG_ON(eb->blocking_writers != 1); | ||
153 | btrfs_assert_spinning_writers_get(eb); | 153 | btrfs_assert_spinning_writers_get(eb); |
154 | /* atomic_dec_and_test implies a barrier */ | 154 | if (--eb->blocking_writers == 0) |
155 | if (atomic_dec_and_test(&eb->blocking_writers)) | 155 | cond_wake_up(&eb->write_lock_wq); |
156 | cond_wake_up_nomb(&eb->write_lock_wq); | ||
157 | } | 156 | } |
158 | 157 | ||
159 | /* | 158 | /* |
@@ -167,12 +166,10 @@ void btrfs_tree_read_lock(struct extent_buffer *eb) | |||
167 | if (trace_btrfs_tree_read_lock_enabled()) | 166 | if (trace_btrfs_tree_read_lock_enabled()) |
168 | start_ns = ktime_get_ns(); | 167 | start_ns = ktime_get_ns(); |
169 | again: | 168 | again: |
170 | BUG_ON(!atomic_read(&eb->blocking_writers) && | ||
171 | current->pid == eb->lock_owner); | ||
172 | |||
173 | read_lock(&eb->lock); | 169 | read_lock(&eb->lock); |
174 | if (atomic_read(&eb->blocking_writers) && | 170 | BUG_ON(eb->blocking_writers == 0 && |
175 | current->pid == eb->lock_owner) { | 171 | current->pid == eb->lock_owner); |
172 | if (eb->blocking_writers && current->pid == eb->lock_owner) { | ||
176 | /* | 173 | /* |
177 | * This extent is already write-locked by our thread. We allow | 174 | * This extent is already write-locked by our thread. We allow |
178 | * an additional read lock to be added because it's for the same | 175 | * an additional read lock to be added because it's for the same |
@@ -185,10 +182,10 @@ again: | |||
185 | trace_btrfs_tree_read_lock(eb, start_ns); | 182 | trace_btrfs_tree_read_lock(eb, start_ns); |
186 | return; | 183 | return; |
187 | } | 184 | } |
188 | if (atomic_read(&eb->blocking_writers)) { | 185 | if (eb->blocking_writers) { |
189 | read_unlock(&eb->lock); | 186 | read_unlock(&eb->lock); |
190 | wait_event(eb->write_lock_wq, | 187 | wait_event(eb->write_lock_wq, |
191 | atomic_read(&eb->blocking_writers) == 0); | 188 | eb->blocking_writers == 0); |
192 | goto again; | 189 | goto again; |
193 | } | 190 | } |
194 | btrfs_assert_tree_read_locks_get(eb); | 191 | btrfs_assert_tree_read_locks_get(eb); |
@@ -203,11 +200,11 @@ again: | |||
203 | */ | 200 | */ |
204 | int btrfs_tree_read_lock_atomic(struct extent_buffer *eb) | 201 | int btrfs_tree_read_lock_atomic(struct extent_buffer *eb) |
205 | { | 202 | { |
206 | if (atomic_read(&eb->blocking_writers)) | 203 | if (eb->blocking_writers) |
207 | return 0; | 204 | return 0; |
208 | 205 | ||
209 | read_lock(&eb->lock); | 206 | read_lock(&eb->lock); |
210 | if (atomic_read(&eb->blocking_writers)) { | 207 | if (eb->blocking_writers) { |
211 | read_unlock(&eb->lock); | 208 | read_unlock(&eb->lock); |
212 | return 0; | 209 | return 0; |
213 | } | 210 | } |
@@ -223,13 +220,13 @@ int btrfs_tree_read_lock_atomic(struct extent_buffer *eb) | |||
223 | */ | 220 | */ |
224 | int btrfs_try_tree_read_lock(struct extent_buffer *eb) | 221 | int btrfs_try_tree_read_lock(struct extent_buffer *eb) |
225 | { | 222 | { |
226 | if (atomic_read(&eb->blocking_writers)) | 223 | if (eb->blocking_writers) |
227 | return 0; | 224 | return 0; |
228 | 225 | ||
229 | if (!read_trylock(&eb->lock)) | 226 | if (!read_trylock(&eb->lock)) |
230 | return 0; | 227 | return 0; |
231 | 228 | ||
232 | if (atomic_read(&eb->blocking_writers)) { | 229 | if (eb->blocking_writers) { |
233 | read_unlock(&eb->lock); | 230 | read_unlock(&eb->lock); |
234 | return 0; | 231 | return 0; |
235 | } | 232 | } |
@@ -245,13 +242,11 @@ int btrfs_try_tree_read_lock(struct extent_buffer *eb) | |||
245 | */ | 242 | */ |
246 | int btrfs_try_tree_write_lock(struct extent_buffer *eb) | 243 | int btrfs_try_tree_write_lock(struct extent_buffer *eb) |
247 | { | 244 | { |
248 | if (atomic_read(&eb->blocking_writers) || | 245 | if (eb->blocking_writers || atomic_read(&eb->blocking_readers)) |
249 | atomic_read(&eb->blocking_readers)) | ||
250 | return 0; | 246 | return 0; |
251 | 247 | ||
252 | write_lock(&eb->lock); | 248 | write_lock(&eb->lock); |
253 | if (atomic_read(&eb->blocking_writers) || | 249 | if (eb->blocking_writers || atomic_read(&eb->blocking_readers)) { |
254 | atomic_read(&eb->blocking_readers)) { | ||
255 | write_unlock(&eb->lock); | 250 | write_unlock(&eb->lock); |
256 | return 0; | 251 | return 0; |
257 | } | 252 | } |
@@ -322,10 +317,9 @@ void btrfs_tree_lock(struct extent_buffer *eb) | |||
322 | WARN_ON(eb->lock_owner == current->pid); | 317 | WARN_ON(eb->lock_owner == current->pid); |
323 | again: | 318 | again: |
324 | wait_event(eb->read_lock_wq, atomic_read(&eb->blocking_readers) == 0); | 319 | wait_event(eb->read_lock_wq, atomic_read(&eb->blocking_readers) == 0); |
325 | wait_event(eb->write_lock_wq, atomic_read(&eb->blocking_writers) == 0); | 320 | wait_event(eb->write_lock_wq, eb->blocking_writers == 0); |
326 | write_lock(&eb->lock); | 321 | write_lock(&eb->lock); |
327 | if (atomic_read(&eb->blocking_readers) || | 322 | if (atomic_read(&eb->blocking_readers) || eb->blocking_writers) { |
328 | atomic_read(&eb->blocking_writers)) { | ||
329 | write_unlock(&eb->lock); | 323 | write_unlock(&eb->lock); |
330 | goto again; | 324 | goto again; |
331 | } | 325 | } |
@@ -340,7 +334,7 @@ again: | |||
340 | */ | 334 | */ |
341 | void btrfs_tree_unlock(struct extent_buffer *eb) | 335 | void btrfs_tree_unlock(struct extent_buffer *eb) |
342 | { | 336 | { |
343 | int blockers = atomic_read(&eb->blocking_writers); | 337 | int blockers = eb->blocking_writers; |
344 | 338 | ||
345 | BUG_ON(blockers > 1); | 339 | BUG_ON(blockers > 1); |
346 | 340 | ||
@@ -351,7 +345,7 @@ void btrfs_tree_unlock(struct extent_buffer *eb) | |||
351 | 345 | ||
352 | if (blockers) { | 346 | if (blockers) { |
353 | btrfs_assert_no_spinning_writers(eb); | 347 | btrfs_assert_no_spinning_writers(eb); |
354 | atomic_dec(&eb->blocking_writers); | 348 | eb->blocking_writers--; |
355 | /* Use the lighter barrier after atomic */ | 349 | /* Use the lighter barrier after atomic */ |
356 | smp_mb__after_atomic(); | 350 | smp_mb__after_atomic(); |
357 | cond_wake_up_nomb(&eb->write_lock_wq); | 351 | cond_wake_up_nomb(&eb->write_lock_wq); |