diff options
author | Wang Shilong <wangsl.fnst@cn.fujitsu.com> | 2014-02-19 06:24:16 -0500 |
---|---|---|
committer | Josef Bacik <jbacik@fb.com> | 2014-03-10 15:16:52 -0400 |
commit | 6cf7f77e6ba55cc1469aaf795507d274402892e9 (patch) | |
tree | 28066f51e6443d9468a11e28c13dab155e239e2c /fs/btrfs/transaction.c | |
parent | 886322e8e787604731e782d36c34327a8970bda9 (diff) |
Btrfs: fix a possible deadlock between scrub and transaction committing
btrfs_scrub_continue() will be called when cleaning up transaction.However,
this can only be called if btrfs_scrub_pause() is called before.
Signed-off-by: Wang Shilong <wangsl.fnst@cn.fujitsu.com>
Signed-off-by: Josef Bacik <jbacik@fb.com>
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r-- | fs/btrfs/transaction.c | 22 |
1 files changed, 11 insertions, 11 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 34cd83184c4a..84da6669f384 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -1578,8 +1578,6 @@ static void cleanup_transaction(struct btrfs_trans_handle *trans, | |||
1578 | 1578 | ||
1579 | trace_btrfs_transaction_commit(root); | 1579 | trace_btrfs_transaction_commit(root); |
1580 | 1580 | ||
1581 | btrfs_scrub_continue(root); | ||
1582 | |||
1583 | if (current->journal_info == trans) | 1581 | if (current->journal_info == trans) |
1584 | current->journal_info = NULL; | 1582 | current->journal_info = NULL; |
1585 | 1583 | ||
@@ -1754,7 +1752,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1754 | /* ->aborted might be set after the previous check, so check it */ | 1752 | /* ->aborted might be set after the previous check, so check it */ |
1755 | if (unlikely(ACCESS_ONCE(cur_trans->aborted))) { | 1753 | if (unlikely(ACCESS_ONCE(cur_trans->aborted))) { |
1756 | ret = cur_trans->aborted; | 1754 | ret = cur_trans->aborted; |
1757 | goto cleanup_transaction; | 1755 | goto scrub_continue; |
1758 | } | 1756 | } |
1759 | /* | 1757 | /* |
1760 | * the reloc mutex makes sure that we stop | 1758 | * the reloc mutex makes sure that we stop |
@@ -1771,7 +1769,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1771 | ret = create_pending_snapshots(trans, root->fs_info); | 1769 | ret = create_pending_snapshots(trans, root->fs_info); |
1772 | if (ret) { | 1770 | if (ret) { |
1773 | mutex_unlock(&root->fs_info->reloc_mutex); | 1771 | mutex_unlock(&root->fs_info->reloc_mutex); |
1774 | goto cleanup_transaction; | 1772 | goto scrub_continue; |
1775 | } | 1773 | } |
1776 | 1774 | ||
1777 | /* | 1775 | /* |
@@ -1787,13 +1785,13 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1787 | ret = btrfs_run_delayed_items(trans, root); | 1785 | ret = btrfs_run_delayed_items(trans, root); |
1788 | if (ret) { | 1786 | if (ret) { |
1789 | mutex_unlock(&root->fs_info->reloc_mutex); | 1787 | mutex_unlock(&root->fs_info->reloc_mutex); |
1790 | goto cleanup_transaction; | 1788 | goto scrub_continue; |
1791 | } | 1789 | } |
1792 | 1790 | ||
1793 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); | 1791 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); |
1794 | if (ret) { | 1792 | if (ret) { |
1795 | mutex_unlock(&root->fs_info->reloc_mutex); | 1793 | mutex_unlock(&root->fs_info->reloc_mutex); |
1796 | goto cleanup_transaction; | 1794 | goto scrub_continue; |
1797 | } | 1795 | } |
1798 | 1796 | ||
1799 | /* | 1797 | /* |
@@ -1823,7 +1821,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1823 | if (ret) { | 1821 | if (ret) { |
1824 | mutex_unlock(&root->fs_info->tree_log_mutex); | 1822 | mutex_unlock(&root->fs_info->tree_log_mutex); |
1825 | mutex_unlock(&root->fs_info->reloc_mutex); | 1823 | mutex_unlock(&root->fs_info->reloc_mutex); |
1826 | goto cleanup_transaction; | 1824 | goto scrub_continue; |
1827 | } | 1825 | } |
1828 | 1826 | ||
1829 | /* | 1827 | /* |
@@ -1844,7 +1842,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1844 | if (ret) { | 1842 | if (ret) { |
1845 | mutex_unlock(&root->fs_info->tree_log_mutex); | 1843 | mutex_unlock(&root->fs_info->tree_log_mutex); |
1846 | mutex_unlock(&root->fs_info->reloc_mutex); | 1844 | mutex_unlock(&root->fs_info->reloc_mutex); |
1847 | goto cleanup_transaction; | 1845 | goto scrub_continue; |
1848 | } | 1846 | } |
1849 | 1847 | ||
1850 | /* | 1848 | /* |
@@ -1855,7 +1853,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1855 | ret = cur_trans->aborted; | 1853 | ret = cur_trans->aborted; |
1856 | mutex_unlock(&root->fs_info->tree_log_mutex); | 1854 | mutex_unlock(&root->fs_info->tree_log_mutex); |
1857 | mutex_unlock(&root->fs_info->reloc_mutex); | 1855 | mutex_unlock(&root->fs_info->reloc_mutex); |
1858 | goto cleanup_transaction; | 1856 | goto scrub_continue; |
1859 | } | 1857 | } |
1860 | 1858 | ||
1861 | btrfs_prepare_extent_commit(trans, root); | 1859 | btrfs_prepare_extent_commit(trans, root); |
@@ -1891,13 +1889,13 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1891 | btrfs_error(root->fs_info, ret, | 1889 | btrfs_error(root->fs_info, ret, |
1892 | "Error while writing out transaction"); | 1890 | "Error while writing out transaction"); |
1893 | mutex_unlock(&root->fs_info->tree_log_mutex); | 1891 | mutex_unlock(&root->fs_info->tree_log_mutex); |
1894 | goto cleanup_transaction; | 1892 | goto scrub_continue; |
1895 | } | 1893 | } |
1896 | 1894 | ||
1897 | ret = write_ctree_super(trans, root, 0); | 1895 | ret = write_ctree_super(trans, root, 0); |
1898 | if (ret) { | 1896 | if (ret) { |
1899 | mutex_unlock(&root->fs_info->tree_log_mutex); | 1897 | mutex_unlock(&root->fs_info->tree_log_mutex); |
1900 | goto cleanup_transaction; | 1898 | goto scrub_continue; |
1901 | } | 1899 | } |
1902 | 1900 | ||
1903 | /* | 1901 | /* |
@@ -1940,6 +1938,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1940 | 1938 | ||
1941 | return ret; | 1939 | return ret; |
1942 | 1940 | ||
1941 | scrub_continue: | ||
1942 | btrfs_scrub_continue(root); | ||
1943 | cleanup_transaction: | 1943 | cleanup_transaction: |
1944 | btrfs_trans_release_metadata(trans, root); | 1944 | btrfs_trans_release_metadata(trans, root); |
1945 | trans->block_rsv = NULL; | 1945 | trans->block_rsv = NULL; |