diff options
| author | Josef Bacik <jbacik@fusionio.com> | 2012-08-01 15:36:24 -0400 |
|---|---|---|
| committer | Chris Mason <chris.mason@oracle.com> | 2012-08-28 16:53:33 -0400 |
| commit | 66657b318e0e443ada229fccd40c8be86cfebdbf (patch) | |
| tree | bf1334fff93556fbc8d82b26a6d5431fd9e74b5c | |
| parent | 1fa11e265fa2562fb713171b6a58e72bb7afd276 (diff) | |
Btrfs: barrier before waitqueue_active
We need a barrir before calling waitqueue_active otherwise we will miss
wakeups. So in places that do atomic_dec(); then atomic_read() use
atomic_dec_return() which imply a memory barrier (see memory-barriers.txt)
and then add an explicit memory barrier everywhere else that need them.
Thanks,
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
| -rw-r--r-- | fs/btrfs/compression.c | 1 | ||||
| -rw-r--r-- | fs/btrfs/delayed-inode.c | 7 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.c | 7 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 4 | ||||
| -rw-r--r-- | fs/btrfs/volumes.c | 3 |
5 files changed, 10 insertions, 12 deletions
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index 86eff48dab78..43d1c5a3a030 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c | |||
| @@ -818,6 +818,7 @@ static void free_workspace(int type, struct list_head *workspace) | |||
| 818 | btrfs_compress_op[idx]->free_workspace(workspace); | 818 | btrfs_compress_op[idx]->free_workspace(workspace); |
| 819 | atomic_dec(alloc_workspace); | 819 | atomic_dec(alloc_workspace); |
| 820 | wake: | 820 | wake: |
| 821 | smp_mb(); | ||
| 821 | if (waitqueue_active(workspace_wait)) | 822 | if (waitqueue_active(workspace_wait)) |
| 822 | wake_up(workspace_wait); | 823 | wake_up(workspace_wait); |
| 823 | } | 824 | } |
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 00deed4ef3ed..07d5eeb1e6f1 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c | |||
| @@ -512,8 +512,8 @@ static void __btrfs_remove_delayed_item(struct btrfs_delayed_item *delayed_item) | |||
| 512 | 512 | ||
| 513 | rb_erase(&delayed_item->rb_node, root); | 513 | rb_erase(&delayed_item->rb_node, root); |
| 514 | delayed_item->delayed_node->count--; | 514 | delayed_item->delayed_node->count--; |
| 515 | atomic_dec(&delayed_root->items); | 515 | if (atomic_dec_return(&delayed_root->items) < |
| 516 | if (atomic_read(&delayed_root->items) < BTRFS_DELAYED_BACKGROUND && | 516 | BTRFS_DELAYED_BACKGROUND && |
| 517 | waitqueue_active(&delayed_root->wait)) | 517 | waitqueue_active(&delayed_root->wait)) |
| 518 | wake_up(&delayed_root->wait); | 518 | wake_up(&delayed_root->wait); |
| 519 | } | 519 | } |
| @@ -1056,8 +1056,7 @@ static void btrfs_release_delayed_inode(struct btrfs_delayed_node *delayed_node) | |||
| 1056 | delayed_node->count--; | 1056 | delayed_node->count--; |
| 1057 | 1057 | ||
| 1058 | delayed_root = delayed_node->root->fs_info->delayed_root; | 1058 | delayed_root = delayed_node->root->fs_info->delayed_root; |
| 1059 | atomic_dec(&delayed_root->items); | 1059 | if (atomic_dec_return(&delayed_root->items) < |
| 1060 | if (atomic_read(&delayed_root->items) < | ||
| 1061 | BTRFS_DELAYED_BACKGROUND && | 1060 | BTRFS_DELAYED_BACKGROUND && |
| 1062 | waitqueue_active(&delayed_root->wait)) | 1061 | waitqueue_active(&delayed_root->wait)) |
| 1063 | wake_up(&delayed_root->wait); | 1062 | wake_up(&delayed_root->wait); |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index a7ad8fc8dc53..dd86a5d88428 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -754,9 +754,7 @@ static void run_one_async_done(struct btrfs_work *work) | |||
| 754 | limit = btrfs_async_submit_limit(fs_info); | 754 | limit = btrfs_async_submit_limit(fs_info); |
| 755 | limit = limit * 2 / 3; | 755 | limit = limit * 2 / 3; |
| 756 | 756 | ||
| 757 | atomic_dec(&fs_info->nr_async_submits); | 757 | if (atomic_dec_return(&fs_info->nr_async_submits) < limit && |
| 758 | |||
| 759 | if (atomic_read(&fs_info->nr_async_submits) < limit && | ||
| 760 | waitqueue_active(&fs_info->async_submit_wait)) | 758 | waitqueue_active(&fs_info->async_submit_wait)) |
| 761 | wake_up(&fs_info->async_submit_wait); | 759 | wake_up(&fs_info->async_submit_wait); |
| 762 | 760 | ||
| @@ -3783,14 +3781,17 @@ int btrfs_cleanup_transaction(struct btrfs_root *root) | |||
| 3783 | /* FIXME: cleanup wait for commit */ | 3781 | /* FIXME: cleanup wait for commit */ |
| 3784 | t->in_commit = 1; | 3782 | t->in_commit = 1; |
| 3785 | t->blocked = 1; | 3783 | t->blocked = 1; |
| 3784 | smp_mb(); | ||
| 3786 | if (waitqueue_active(&root->fs_info->transaction_blocked_wait)) | 3785 | if (waitqueue_active(&root->fs_info->transaction_blocked_wait)) |
| 3787 | wake_up(&root->fs_info->transaction_blocked_wait); | 3786 | wake_up(&root->fs_info->transaction_blocked_wait); |
| 3788 | 3787 | ||
| 3789 | t->blocked = 0; | 3788 | t->blocked = 0; |
| 3789 | smp_mb(); | ||
| 3790 | if (waitqueue_active(&root->fs_info->transaction_wait)) | 3790 | if (waitqueue_active(&root->fs_info->transaction_wait)) |
| 3791 | wake_up(&root->fs_info->transaction_wait); | 3791 | wake_up(&root->fs_info->transaction_wait); |
| 3792 | 3792 | ||
| 3793 | t->commit_done = 1; | 3793 | t->commit_done = 1; |
| 3794 | smp_mb(); | ||
| 3794 | if (waitqueue_active(&t->commit_wait)) | 3795 | if (waitqueue_active(&t->commit_wait)) |
| 3795 | wake_up(&t->commit_wait); | 3796 | wake_up(&t->commit_wait); |
| 3796 | 3797 | ||
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 2d65c52b0944..97baf00b40d1 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -1007,9 +1007,7 @@ static noinline void async_cow_submit(struct btrfs_work *work) | |||
| 1007 | nr_pages = (async_cow->end - async_cow->start + PAGE_CACHE_SIZE) >> | 1007 | nr_pages = (async_cow->end - async_cow->start + PAGE_CACHE_SIZE) >> |
| 1008 | PAGE_CACHE_SHIFT; | 1008 | PAGE_CACHE_SHIFT; |
| 1009 | 1009 | ||
| 1010 | atomic_sub(nr_pages, &root->fs_info->async_delalloc_pages); | 1010 | if (atomic_sub_return(nr_pages, &root->fs_info->async_delalloc_pages) < |
| 1011 | |||
| 1012 | if (atomic_read(&root->fs_info->async_delalloc_pages) < | ||
| 1013 | 5 * 1024 * 1024 && | 1011 | 5 * 1024 * 1024 && |
| 1014 | waitqueue_active(&root->fs_info->async_submit_wait)) | 1012 | waitqueue_active(&root->fs_info->async_submit_wait)) |
| 1015 | wake_up(&root->fs_info->async_submit_wait); | 1013 | wake_up(&root->fs_info->async_submit_wait); |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 3b394503bd4e..0b1e69d380dd 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
| @@ -227,9 +227,8 @@ loop_lock: | |||
| 227 | cur = pending; | 227 | cur = pending; |
| 228 | pending = pending->bi_next; | 228 | pending = pending->bi_next; |
| 229 | cur->bi_next = NULL; | 229 | cur->bi_next = NULL; |
| 230 | atomic_dec(&fs_info->nr_async_bios); | ||
| 231 | 230 | ||
| 232 | if (atomic_read(&fs_info->nr_async_bios) < limit && | 231 | if (atomic_dec_return(&fs_info->nr_async_bios) < limit && |
| 233 | waitqueue_active(&fs_info->async_submit_wait)) | 232 | waitqueue_active(&fs_info->async_submit_wait)) |
| 234 | wake_up(&fs_info->async_submit_wait); | 233 | wake_up(&fs_info->async_submit_wait); |
| 235 | 234 | ||
