diff options
author | Chris Mason <clm@fb.com> | 2015-10-12 19:24:40 -0400 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2015-10-12 19:24:40 -0400 |
commit | 6db4a7335dd701a0e20275440ee057d3db2a7ae3 (patch) | |
tree | c0734d7411806ef91bfeb615bf528ffb349938fe | |
parent | 62fb50ab7c903357c92cef2f7677235b92ac575f (diff) | |
parent | ee86395458072760d62e66aad10a5e9e8902b8cf (diff) |
Merge branch 'fix/waitqueue-barriers' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux into for-linus-4.4
-rw-r--r-- | fs/btrfs/compression.c | 3 | ||||
-rw-r--r-- | fs/btrfs/delayed-inode.c | 4 | ||||
-rw-r--r-- | fs/btrfs/dev-replace.c | 3 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 3 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 3 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 3 | ||||
-rw-r--r-- | fs/btrfs/locking.c | 12 | ||||
-rw-r--r-- | fs/btrfs/ordered-data.c | 6 | ||||
-rw-r--r-- | fs/btrfs/raid56.c | 6 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 9 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 14 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 3 |
12 files changed, 62 insertions, 7 deletions
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index 57ee8ca29b06..3a9317ce67f8 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c | |||
@@ -839,6 +839,9 @@ static void free_workspace(int type, struct list_head *workspace) | |||
839 | btrfs_compress_op[idx]->free_workspace(workspace); | 839 | btrfs_compress_op[idx]->free_workspace(workspace); |
840 | atomic_dec(alloc_workspace); | 840 | atomic_dec(alloc_workspace); |
841 | wake: | 841 | wake: |
842 | /* | ||
843 | * Make sure counter is updated before we wake up waiters. | ||
844 | */ | ||
842 | smp_mb(); | 845 | smp_mb(); |
843 | if (waitqueue_active(workspace_wait)) | 846 | if (waitqueue_active(workspace_wait)) |
844 | wake_up(workspace_wait); | 847 | wake_up(workspace_wait); |
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index a2ae42720a6a..e0941fbb913c 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c | |||
@@ -463,6 +463,10 @@ static int __btrfs_add_delayed_deletion_item(struct btrfs_delayed_node *node, | |||
463 | static void finish_one_item(struct btrfs_delayed_root *delayed_root) | 463 | static void finish_one_item(struct btrfs_delayed_root *delayed_root) |
464 | { | 464 | { |
465 | int seq = atomic_inc_return(&delayed_root->items_seq); | 465 | int seq = atomic_inc_return(&delayed_root->items_seq); |
466 | |||
467 | /* | ||
468 | * atomic_dec_return implies a barrier for waitqueue_active | ||
469 | */ | ||
466 | if ((atomic_dec_return(&delayed_root->items) < | 470 | if ((atomic_dec_return(&delayed_root->items) < |
467 | BTRFS_DELAYED_BACKGROUND || seq % BTRFS_DELAYED_BATCH == 0) && | 471 | BTRFS_DELAYED_BACKGROUND || seq % BTRFS_DELAYED_BATCH == 0) && |
468 | waitqueue_active(&delayed_root->wait)) | 472 | waitqueue_active(&delayed_root->wait)) |
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c index a64ca942b63f..1e668fb7dd4c 100644 --- a/fs/btrfs/dev-replace.c +++ b/fs/btrfs/dev-replace.c | |||
@@ -454,8 +454,7 @@ static void btrfs_rm_dev_replace_blocked(struct btrfs_fs_info *fs_info) | |||
454 | static void btrfs_rm_dev_replace_unblocked(struct btrfs_fs_info *fs_info) | 454 | static void btrfs_rm_dev_replace_unblocked(struct btrfs_fs_info *fs_info) |
455 | { | 455 | { |
456 | clear_bit(BTRFS_FS_STATE_DEV_REPLACING, &fs_info->fs_state); | 456 | clear_bit(BTRFS_FS_STATE_DEV_REPLACING, &fs_info->fs_state); |
457 | if (waitqueue_active(&fs_info->replace_wait)) | 457 | wake_up(&fs_info->replace_wait); |
458 | wake_up(&fs_info->replace_wait); | ||
459 | } | 458 | } |
460 | 459 | ||
461 | static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info, | 460 | static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info, |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 7f934cccc98d..a42c1f575ef7 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -801,6 +801,9 @@ static void run_one_async_done(struct btrfs_work *work) | |||
801 | limit = btrfs_async_submit_limit(fs_info); | 801 | limit = btrfs_async_submit_limit(fs_info); |
802 | limit = limit * 2 / 3; | 802 | limit = limit * 2 / 3; |
803 | 803 | ||
804 | /* | ||
805 | * atomic_dec_return implies a barrier for waitqueue_active | ||
806 | */ | ||
804 | if (atomic_dec_return(&fs_info->nr_async_submits) < limit && | 807 | if (atomic_dec_return(&fs_info->nr_async_submits) < limit && |
805 | waitqueue_active(&fs_info->async_submit_wait)) | 808 | waitqueue_active(&fs_info->async_submit_wait)) |
806 | wake_up(&fs_info->async_submit_wait); | 809 | wake_up(&fs_info->async_submit_wait); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 92a5b4cad2ab..522fb45d472a 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -10372,8 +10372,7 @@ void btrfs_end_write_no_snapshoting(struct btrfs_root *root) | |||
10372 | { | 10372 | { |
10373 | percpu_counter_dec(&root->subv_writers->counter); | 10373 | percpu_counter_dec(&root->subv_writers->counter); |
10374 | /* | 10374 | /* |
10375 | * Make sure counter is updated before we wake up | 10375 | * Make sure counter is updated before we wake up waiters. |
10376 | * waiters. | ||
10377 | */ | 10376 | */ |
10378 | smp_mb(); | 10377 | smp_mb(); |
10379 | if (waitqueue_active(&root->subv_writers->wait)) | 10378 | if (waitqueue_active(&root->subv_writers->wait)) |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 25eb814c302f..208db4e835f0 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -1096,6 +1096,9 @@ static noinline void async_cow_submit(struct btrfs_work *work) | |||
1096 | nr_pages = (async_cow->end - async_cow->start + PAGE_CACHE_SIZE) >> | 1096 | nr_pages = (async_cow->end - async_cow->start + PAGE_CACHE_SIZE) >> |
1097 | PAGE_CACHE_SHIFT; | 1097 | PAGE_CACHE_SHIFT; |
1098 | 1098 | ||
1099 | /* | ||
1100 | * atomic_sub_return implies a barrier for waitqueue_active | ||
1101 | */ | ||
1099 | if (atomic_sub_return(nr_pages, &root->fs_info->async_delalloc_pages) < | 1102 | if (atomic_sub_return(nr_pages, &root->fs_info->async_delalloc_pages) < |
1100 | 5 * 1024 * 1024 && | 1103 | 5 * 1024 * 1024 && |
1101 | waitqueue_active(&root->fs_info->async_submit_wait)) | 1104 | waitqueue_active(&root->fs_info->async_submit_wait)) |
diff --git a/fs/btrfs/locking.c b/fs/btrfs/locking.c index d7e6baf1b205..8077461fc56a 100644 --- a/fs/btrfs/locking.c +++ b/fs/btrfs/locking.c | |||
@@ -79,6 +79,9 @@ void btrfs_clear_lock_blocking_rw(struct extent_buffer *eb, int rw) | |||
79 | write_lock(&eb->lock); | 79 | write_lock(&eb->lock); |
80 | WARN_ON(atomic_read(&eb->spinning_writers)); | 80 | WARN_ON(atomic_read(&eb->spinning_writers)); |
81 | atomic_inc(&eb->spinning_writers); | 81 | atomic_inc(&eb->spinning_writers); |
82 | /* | ||
83 | * atomic_dec_and_test implies a barrier for waitqueue_active | ||
84 | */ | ||
82 | if (atomic_dec_and_test(&eb->blocking_writers) && | 85 | if (atomic_dec_and_test(&eb->blocking_writers) && |
83 | waitqueue_active(&eb->write_lock_wq)) | 86 | waitqueue_active(&eb->write_lock_wq)) |
84 | wake_up(&eb->write_lock_wq); | 87 | wake_up(&eb->write_lock_wq); |
@@ -86,6 +89,9 @@ void btrfs_clear_lock_blocking_rw(struct extent_buffer *eb, int rw) | |||
86 | BUG_ON(atomic_read(&eb->blocking_readers) == 0); | 89 | BUG_ON(atomic_read(&eb->blocking_readers) == 0); |
87 | read_lock(&eb->lock); | 90 | read_lock(&eb->lock); |
88 | atomic_inc(&eb->spinning_readers); | 91 | atomic_inc(&eb->spinning_readers); |
92 | /* | ||
93 | * atomic_dec_and_test implies a barrier for waitqueue_active | ||
94 | */ | ||
89 | if (atomic_dec_and_test(&eb->blocking_readers) && | 95 | if (atomic_dec_and_test(&eb->blocking_readers) && |
90 | waitqueue_active(&eb->read_lock_wq)) | 96 | waitqueue_active(&eb->read_lock_wq)) |
91 | wake_up(&eb->read_lock_wq); | 97 | wake_up(&eb->read_lock_wq); |
@@ -229,6 +235,9 @@ void btrfs_tree_read_unlock_blocking(struct extent_buffer *eb) | |||
229 | } | 235 | } |
230 | btrfs_assert_tree_read_locked(eb); | 236 | btrfs_assert_tree_read_locked(eb); |
231 | WARN_ON(atomic_read(&eb->blocking_readers) == 0); | 237 | WARN_ON(atomic_read(&eb->blocking_readers) == 0); |
238 | /* | ||
239 | * atomic_dec_and_test implies a barrier for waitqueue_active | ||
240 | */ | ||
232 | if (atomic_dec_and_test(&eb->blocking_readers) && | 241 | if (atomic_dec_and_test(&eb->blocking_readers) && |
233 | waitqueue_active(&eb->read_lock_wq)) | 242 | waitqueue_active(&eb->read_lock_wq)) |
234 | wake_up(&eb->read_lock_wq); | 243 | wake_up(&eb->read_lock_wq); |
@@ -280,6 +289,9 @@ void btrfs_tree_unlock(struct extent_buffer *eb) | |||
280 | if (blockers) { | 289 | if (blockers) { |
281 | WARN_ON(atomic_read(&eb->spinning_writers)); | 290 | WARN_ON(atomic_read(&eb->spinning_writers)); |
282 | atomic_dec(&eb->blocking_writers); | 291 | atomic_dec(&eb->blocking_writers); |
292 | /* | ||
293 | * Make sure counter is updated before we wake up waiters. | ||
294 | */ | ||
283 | smp_mb(); | 295 | smp_mb(); |
284 | if (waitqueue_active(&eb->write_lock_wq)) | 296 | if (waitqueue_active(&eb->write_lock_wq)) |
285 | wake_up(&eb->write_lock_wq); | 297 | wake_up(&eb->write_lock_wq); |
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 52170cf1757e..071005f008c1 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
@@ -345,6 +345,9 @@ int btrfs_dec_test_first_ordered_pending(struct inode *inode, | |||
345 | 345 | ||
346 | if (entry->bytes_left == 0) { | 346 | if (entry->bytes_left == 0) { |
347 | ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags); | 347 | ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags); |
348 | /* | ||
349 | * Implicit memory barrier after test_and_set_bit | ||
350 | */ | ||
348 | if (waitqueue_active(&entry->wait)) | 351 | if (waitqueue_active(&entry->wait)) |
349 | wake_up(&entry->wait); | 352 | wake_up(&entry->wait); |
350 | } else { | 353 | } else { |
@@ -409,6 +412,9 @@ have_entry: | |||
409 | 412 | ||
410 | if (entry->bytes_left == 0) { | 413 | if (entry->bytes_left == 0) { |
411 | ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags); | 414 | ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags); |
415 | /* | ||
416 | * Implicit memory barrier after test_and_set_bit | ||
417 | */ | ||
412 | if (waitqueue_active(&entry->wait)) | 418 | if (waitqueue_active(&entry->wait)) |
413 | wake_up(&entry->wait); | 419 | wake_up(&entry->wait); |
414 | } else { | 420 | } else { |
diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c index fcf7265ca46f..1a33d3eb36de 100644 --- a/fs/btrfs/raid56.c +++ b/fs/btrfs/raid56.c | |||
@@ -810,7 +810,11 @@ static noinline void unlock_stripe(struct btrfs_raid_bio *rbio) | |||
810 | } | 810 | } |
811 | 811 | ||
812 | goto done_nolock; | 812 | goto done_nolock; |
813 | } else if (waitqueue_active(&h->wait)) { | 813 | /* |
814 | * The barrier for this waitqueue_active is not needed, | ||
815 | * we're protected by h->lock and can't miss a wakeup. | ||
816 | */ | ||
817 | } else if (waitqueue_active(&h->wait)) { | ||
814 | spin_unlock(&rbio->bio_list_lock); | 818 | spin_unlock(&rbio->bio_list_lock); |
815 | spin_unlock_irqrestore(&h->lock, flags); | 819 | spin_unlock_irqrestore(&h->lock, flags); |
816 | wake_up(&h->wait); | 820 | wake_up(&h->wait); |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 76354bb1312c..47fd27031a20 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -82,6 +82,12 @@ void btrfs_put_transaction(struct btrfs_transaction *transaction) | |||
82 | static void clear_btree_io_tree(struct extent_io_tree *tree) | 82 | static void clear_btree_io_tree(struct extent_io_tree *tree) |
83 | { | 83 | { |
84 | spin_lock(&tree->lock); | 84 | spin_lock(&tree->lock); |
85 | /* | ||
86 | * Do a single barrier for the waitqueue_active check here, the state | ||
87 | * of the waitqueue should not change once clear_btree_io_tree is | ||
88 | * called. | ||
89 | */ | ||
90 | smp_mb(); | ||
85 | while (!RB_EMPTY_ROOT(&tree->state)) { | 91 | while (!RB_EMPTY_ROOT(&tree->state)) { |
86 | struct rb_node *node; | 92 | struct rb_node *node; |
87 | struct extent_state *state; | 93 | struct extent_state *state; |
@@ -856,6 +862,9 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
856 | atomic_dec(&cur_trans->num_writers); | 862 | atomic_dec(&cur_trans->num_writers); |
857 | extwriter_counter_dec(cur_trans, trans->type); | 863 | extwriter_counter_dec(cur_trans, trans->type); |
858 | 864 | ||
865 | /* | ||
866 | * Make sure counter is updated before we wake up waiters. | ||
867 | */ | ||
859 | smp_mb(); | 868 | smp_mb(); |
860 | if (waitqueue_active(&cur_trans->writer_wait)) | 869 | if (waitqueue_active(&cur_trans->writer_wait)) |
861 | wake_up(&cur_trans->writer_wait); | 870 | wake_up(&cur_trans->writer_wait); |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index c3f9a9c71f28..1fffe8845c09 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -229,7 +229,9 @@ int btrfs_pin_log_trans(struct btrfs_root *root) | |||
229 | void btrfs_end_log_trans(struct btrfs_root *root) | 229 | void btrfs_end_log_trans(struct btrfs_root *root) |
230 | { | 230 | { |
231 | if (atomic_dec_and_test(&root->log_writers)) { | 231 | if (atomic_dec_and_test(&root->log_writers)) { |
232 | smp_mb(); | 232 | /* |
233 | * Implicit memory barrier after atomic_dec_and_test | ||
234 | */ | ||
233 | if (waitqueue_active(&root->log_writer_wait)) | 235 | if (waitqueue_active(&root->log_writer_wait)) |
234 | wake_up(&root->log_writer_wait); | 236 | wake_up(&root->log_writer_wait); |
235 | } | 237 | } |
@@ -2820,7 +2822,9 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
2820 | 2822 | ||
2821 | mutex_lock(&log_root_tree->log_mutex); | 2823 | mutex_lock(&log_root_tree->log_mutex); |
2822 | if (atomic_dec_and_test(&log_root_tree->log_writers)) { | 2824 | if (atomic_dec_and_test(&log_root_tree->log_writers)) { |
2823 | smp_mb(); | 2825 | /* |
2826 | * Implicit memory barrier after atomic_dec_and_test | ||
2827 | */ | ||
2824 | if (waitqueue_active(&log_root_tree->log_writer_wait)) | 2828 | if (waitqueue_active(&log_root_tree->log_writer_wait)) |
2825 | wake_up(&log_root_tree->log_writer_wait); | 2829 | wake_up(&log_root_tree->log_writer_wait); |
2826 | } | 2830 | } |
@@ -2950,6 +2954,9 @@ out_wake_log_root: | |||
2950 | atomic_set(&log_root_tree->log_commit[index2], 0); | 2954 | atomic_set(&log_root_tree->log_commit[index2], 0); |
2951 | mutex_unlock(&log_root_tree->log_mutex); | 2955 | mutex_unlock(&log_root_tree->log_mutex); |
2952 | 2956 | ||
2957 | /* | ||
2958 | * The barrier before waitqueue_active is implied by mutex_unlock | ||
2959 | */ | ||
2953 | if (waitqueue_active(&log_root_tree->log_commit_wait[index2])) | 2960 | if (waitqueue_active(&log_root_tree->log_commit_wait[index2])) |
2954 | wake_up(&log_root_tree->log_commit_wait[index2]); | 2961 | wake_up(&log_root_tree->log_commit_wait[index2]); |
2955 | out: | 2962 | out: |
@@ -2961,6 +2968,9 @@ out: | |||
2961 | atomic_set(&root->log_commit[index1], 0); | 2968 | atomic_set(&root->log_commit[index1], 0); |
2962 | mutex_unlock(&root->log_mutex); | 2969 | mutex_unlock(&root->log_mutex); |
2963 | 2970 | ||
2971 | /* | ||
2972 | * The barrier before waitqueue_active is implied by mutex_unlock | ||
2973 | */ | ||
2964 | if (waitqueue_active(&root->log_commit_wait[index1])) | 2974 | if (waitqueue_active(&root->log_commit_wait[index1])) |
2965 | wake_up(&root->log_commit_wait[index1]); | 2975 | wake_up(&root->log_commit_wait[index1]); |
2966 | return ret; | 2976 | return ret; |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index dd644d767782..cc1cc3559045 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -344,6 +344,9 @@ loop_lock: | |||
344 | pending = pending->bi_next; | 344 | pending = pending->bi_next; |
345 | cur->bi_next = NULL; | 345 | cur->bi_next = NULL; |
346 | 346 | ||
347 | /* | ||
348 | * atomic_dec_return implies a barrier for waitqueue_active | ||
349 | */ | ||
347 | if (atomic_dec_return(&fs_info->nr_async_bios) < limit && | 350 | if (atomic_dec_return(&fs_info->nr_async_bios) < limit && |
348 | waitqueue_active(&fs_info->async_submit_wait)) | 351 | waitqueue_active(&fs_info->async_submit_wait)) |
349 | wake_up(&fs_info->async_submit_wait); | 352 | wake_up(&fs_info->async_submit_wait); |