diff options
author | Liu Bo <bo.li.liu@oracle.com> | 2017-09-01 18:14:30 -0400 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2017-10-30 07:27:55 -0400 |
commit | 49e83f5735cf1aca03ca8b4eadca475c1f3b0b14 (patch) | |
tree | 39541ef4b34a4fcbd9efb91ed90dac62f5567e4c /fs/btrfs/tree-log.c | |
parent | 45bac0f3d24a76f127a118e7b95a54e616449d16 (diff) |
Btrfs: protect conditions within root->log_mutex while waiting
Both wait_for_commit() and wait_for_writer() are checking the
condition out of the mutex lock.
This refactors code a bit to be lock safe.
Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r-- | fs/btrfs/tree-log.c | 30 |
1 files changed, 16 insertions, 14 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index c800d067fcbf..963f22b17508 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -2699,34 +2699,36 @@ static void wait_log_commit(struct btrfs_root *root, int transid) | |||
2699 | * so we know that if ours is more than 2 older than the | 2699 | * so we know that if ours is more than 2 older than the |
2700 | * current transaction, we're done | 2700 | * current transaction, we're done |
2701 | */ | 2701 | */ |
2702 | do { | 2702 | for (;;) { |
2703 | prepare_to_wait(&root->log_commit_wait[index], | 2703 | prepare_to_wait(&root->log_commit_wait[index], |
2704 | &wait, TASK_UNINTERRUPTIBLE); | 2704 | &wait, TASK_UNINTERRUPTIBLE); |
2705 | mutex_unlock(&root->log_mutex); | ||
2706 | 2705 | ||
2707 | if (root->log_transid_committed < transid && | 2706 | if (!(root->log_transid_committed < transid && |
2708 | atomic_read(&root->log_commit[index])) | 2707 | atomic_read(&root->log_commit[index]))) |
2709 | schedule(); | 2708 | break; |
2710 | 2709 | ||
2711 | finish_wait(&root->log_commit_wait[index], &wait); | 2710 | mutex_unlock(&root->log_mutex); |
2711 | schedule(); | ||
2712 | mutex_lock(&root->log_mutex); | 2712 | mutex_lock(&root->log_mutex); |
2713 | } while (root->log_transid_committed < transid && | 2713 | } |
2714 | atomic_read(&root->log_commit[index])); | 2714 | finish_wait(&root->log_commit_wait[index], &wait); |
2715 | } | 2715 | } |
2716 | 2716 | ||
2717 | static void wait_for_writer(struct btrfs_root *root) | 2717 | static void wait_for_writer(struct btrfs_root *root) |
2718 | { | 2718 | { |
2719 | DEFINE_WAIT(wait); | 2719 | DEFINE_WAIT(wait); |
2720 | 2720 | ||
2721 | while (atomic_read(&root->log_writers)) { | 2721 | for (;;) { |
2722 | prepare_to_wait(&root->log_writer_wait, | 2722 | prepare_to_wait(&root->log_writer_wait, &wait, |
2723 | &wait, TASK_UNINTERRUPTIBLE); | 2723 | TASK_UNINTERRUPTIBLE); |
2724 | if (!atomic_read(&root->log_writers)) | ||
2725 | break; | ||
2726 | |||
2724 | mutex_unlock(&root->log_mutex); | 2727 | mutex_unlock(&root->log_mutex); |
2725 | if (atomic_read(&root->log_writers)) | 2728 | schedule(); |
2726 | schedule(); | ||
2727 | finish_wait(&root->log_writer_wait, &wait); | ||
2728 | mutex_lock(&root->log_mutex); | 2729 | mutex_lock(&root->log_mutex); |
2729 | } | 2730 | } |
2731 | finish_wait(&root->log_writer_wait, &wait); | ||
2730 | } | 2732 | } |
2731 | 2733 | ||
2732 | static inline void btrfs_remove_log_ctx(struct btrfs_root *root, | 2734 | static inline void btrfs_remove_log_ctx(struct btrfs_root *root, |