diff options
Diffstat (limited to 'fs/btrfs/locking.c')
-rw-r--r-- | fs/btrfs/locking.c | 50 |
1 files changed, 26 insertions, 24 deletions
diff --git a/fs/btrfs/locking.c b/fs/btrfs/locking.c index 1da768e5ef75..7201d000f61d 100644 --- a/fs/btrfs/locking.c +++ b/fs/btrfs/locking.c | |||
@@ -14,35 +14,37 @@ | |||
14 | 14 | ||
15 | static void btrfs_assert_tree_read_locked(struct extent_buffer *eb); | 15 | static void btrfs_assert_tree_read_locked(struct extent_buffer *eb); |
16 | 16 | ||
17 | /* | 17 | void btrfs_set_lock_blocking_read(struct extent_buffer *eb) |
18 | * if we currently have a spinning reader or writer lock | ||
19 | * (indicated by the rw flag) this will bump the count | ||
20 | * of blocking holders and drop the spinlock. | ||
21 | */ | ||
22 | void btrfs_set_lock_blocking_rw(struct extent_buffer *eb, int rw) | ||
23 | { | 18 | { |
24 | /* | 19 | /* |
25 | * no lock is required. The lock owner may change if | 20 | * No lock is required. The lock owner may change if we have a read |
26 | * we have a read lock, but it won't change to or away | 21 | * lock, but it won't change to or away from us. If we have the write |
27 | * from us. If we have the write lock, we are the owner | 22 | * lock, we are the owner and it'll never change. |
28 | * and it'll never change. | ||
29 | */ | 23 | */ |
30 | if (eb->lock_nested && current->pid == eb->lock_owner) | 24 | if (eb->lock_nested && current->pid == eb->lock_owner) |
31 | return; | 25 | return; |
32 | if (rw == BTRFS_WRITE_LOCK) { | 26 | btrfs_assert_tree_read_locked(eb); |
33 | if (atomic_read(&eb->blocking_writers) == 0) { | 27 | atomic_inc(&eb->blocking_readers); |
34 | WARN_ON(atomic_read(&eb->spinning_writers) != 1); | 28 | WARN_ON(atomic_read(&eb->spinning_readers) == 0); |
35 | atomic_dec(&eb->spinning_writers); | 29 | atomic_dec(&eb->spinning_readers); |
36 | btrfs_assert_tree_locked(eb); | 30 | read_unlock(&eb->lock); |
37 | atomic_inc(&eb->blocking_writers); | 31 | } |
38 | write_unlock(&eb->lock); | 32 | |
39 | } | 33 | void btrfs_set_lock_blocking_write(struct extent_buffer *eb) |
40 | } else if (rw == BTRFS_READ_LOCK) { | 34 | { |
41 | btrfs_assert_tree_read_locked(eb); | 35 | /* |
42 | atomic_inc(&eb->blocking_readers); | 36 | * No lock is required. The lock owner may change if we have a read |
43 | WARN_ON(atomic_read(&eb->spinning_readers) == 0); | 37 | * lock, but it won't change to or away from us. If we have the write |
44 | atomic_dec(&eb->spinning_readers); | 38 | * lock, we are the owner and it'll never change. |
45 | read_unlock(&eb->lock); | 39 | */ |
40 | if (eb->lock_nested && current->pid == eb->lock_owner) | ||
41 | return; | ||
42 | if (atomic_read(&eb->blocking_writers) == 0) { | ||
43 | WARN_ON(atomic_read(&eb->spinning_writers) != 1); | ||
44 | atomic_dec(&eb->spinning_writers); | ||
45 | btrfs_assert_tree_locked(eb); | ||
46 | atomic_inc(&eb->blocking_writers); | ||
47 | write_unlock(&eb->lock); | ||
46 | } | 48 | } |
47 | } | 49 | } |
48 | 50 | ||