diff options
Diffstat (limited to 'fs/btrfs/locking.c')
| -rw-r--r-- | fs/btrfs/locking.c | 14 | 
1 files changed, 9 insertions, 5 deletions
| diff --git a/fs/btrfs/locking.c b/fs/btrfs/locking.c index 272f911203ff..a44eff074805 100644 --- a/fs/btrfs/locking.c +++ b/fs/btrfs/locking.c | |||
| @@ -78,13 +78,15 @@ void btrfs_clear_lock_blocking_rw(struct extent_buffer *eb, int rw) | |||
| 78 | write_lock(&eb->lock); | 78 | write_lock(&eb->lock); | 
| 79 | WARN_ON(atomic_read(&eb->spinning_writers)); | 79 | WARN_ON(atomic_read(&eb->spinning_writers)); | 
| 80 | atomic_inc(&eb->spinning_writers); | 80 | atomic_inc(&eb->spinning_writers); | 
| 81 | if (atomic_dec_and_test(&eb->blocking_writers)) | 81 | if (atomic_dec_and_test(&eb->blocking_writers) && | 
| 82 | waitqueue_active(&eb->write_lock_wq)) | ||
| 82 | wake_up(&eb->write_lock_wq); | 83 | wake_up(&eb->write_lock_wq); | 
| 83 | } else if (rw == BTRFS_READ_LOCK_BLOCKING) { | 84 | } else if (rw == BTRFS_READ_LOCK_BLOCKING) { | 
| 84 | BUG_ON(atomic_read(&eb->blocking_readers) == 0); | 85 | BUG_ON(atomic_read(&eb->blocking_readers) == 0); | 
| 85 | read_lock(&eb->lock); | 86 | read_lock(&eb->lock); | 
| 86 | atomic_inc(&eb->spinning_readers); | 87 | atomic_inc(&eb->spinning_readers); | 
| 87 | if (atomic_dec_and_test(&eb->blocking_readers)) | 88 | if (atomic_dec_and_test(&eb->blocking_readers) && | 
| 89 | waitqueue_active(&eb->read_lock_wq)) | ||
| 88 | wake_up(&eb->read_lock_wq); | 90 | wake_up(&eb->read_lock_wq); | 
| 89 | } | 91 | } | 
| 90 | return; | 92 | return; | 
| @@ -199,7 +201,8 @@ void btrfs_tree_read_unlock_blocking(struct extent_buffer *eb) | |||
| 199 | } | 201 | } | 
| 200 | btrfs_assert_tree_read_locked(eb); | 202 | btrfs_assert_tree_read_locked(eb); | 
| 201 | WARN_ON(atomic_read(&eb->blocking_readers) == 0); | 203 | WARN_ON(atomic_read(&eb->blocking_readers) == 0); | 
| 202 | if (atomic_dec_and_test(&eb->blocking_readers)) | 204 | if (atomic_dec_and_test(&eb->blocking_readers) && | 
| 205 | waitqueue_active(&eb->read_lock_wq)) | ||
| 203 | wake_up(&eb->read_lock_wq); | 206 | wake_up(&eb->read_lock_wq); | 
| 204 | atomic_dec(&eb->read_locks); | 207 | atomic_dec(&eb->read_locks); | 
| 205 | } | 208 | } | 
| @@ -247,8 +250,9 @@ void btrfs_tree_unlock(struct extent_buffer *eb) | |||
| 247 | if (blockers) { | 250 | if (blockers) { | 
| 248 | WARN_ON(atomic_read(&eb->spinning_writers)); | 251 | WARN_ON(atomic_read(&eb->spinning_writers)); | 
| 249 | atomic_dec(&eb->blocking_writers); | 252 | atomic_dec(&eb->blocking_writers); | 
| 250 | smp_wmb(); | 253 | smp_mb(); | 
| 251 | wake_up(&eb->write_lock_wq); | 254 | if (waitqueue_active(&eb->write_lock_wq)) | 
| 255 | wake_up(&eb->write_lock_wq); | ||
| 252 | } else { | 256 | } else { | 
| 253 | WARN_ON(atomic_read(&eb->spinning_writers) != 1); | 257 | WARN_ON(atomic_read(&eb->spinning_writers) != 1); | 
| 254 | atomic_dec(&eb->spinning_writers); | 258 | atomic_dec(&eb->spinning_writers); | 
