diff options
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 3f43bfea3684..a9aadb2ad525 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -1751,6 +1751,7 @@ static int cleaner_kthread(void *arg) | |||
1751 | { | 1751 | { |
1752 | struct btrfs_root *root = arg; | 1752 | struct btrfs_root *root = arg; |
1753 | int again; | 1753 | int again; |
1754 | struct btrfs_trans_handle *trans; | ||
1754 | 1755 | ||
1755 | do { | 1756 | do { |
1756 | again = 0; | 1757 | again = 0; |
@@ -1772,7 +1773,6 @@ static int cleaner_kthread(void *arg) | |||
1772 | } | 1773 | } |
1773 | 1774 | ||
1774 | btrfs_run_delayed_iputs(root); | 1775 | btrfs_run_delayed_iputs(root); |
1775 | btrfs_delete_unused_bgs(root->fs_info); | ||
1776 | again = btrfs_clean_one_deleted_snapshot(root); | 1776 | again = btrfs_clean_one_deleted_snapshot(root); |
1777 | mutex_unlock(&root->fs_info->cleaner_mutex); | 1777 | mutex_unlock(&root->fs_info->cleaner_mutex); |
1778 | 1778 | ||
@@ -1781,6 +1781,16 @@ static int cleaner_kthread(void *arg) | |||
1781 | * needn't do anything special here. | 1781 | * needn't do anything special here. |
1782 | */ | 1782 | */ |
1783 | btrfs_run_defrag_inodes(root->fs_info); | 1783 | btrfs_run_defrag_inodes(root->fs_info); |
1784 | |||
1785 | /* | ||
1786 | * Acquires fs_info->delete_unused_bgs_mutex to avoid racing | ||
1787 | * with relocation (btrfs_relocate_chunk) and relocation | ||
1788 | * acquires fs_info->cleaner_mutex (btrfs_relocate_block_group) | ||
1789 | * after acquiring fs_info->delete_unused_bgs_mutex. So we | ||
1790 | * can't hold, nor need to, fs_info->cleaner_mutex when deleting | ||
1791 | * unused block groups. | ||
1792 | */ | ||
1793 | btrfs_delete_unused_bgs(root->fs_info); | ||
1784 | sleep: | 1794 | sleep: |
1785 | if (!try_to_freeze() && !again) { | 1795 | if (!try_to_freeze() && !again) { |
1786 | set_current_state(TASK_INTERRUPTIBLE); | 1796 | set_current_state(TASK_INTERRUPTIBLE); |
@@ -1789,6 +1799,34 @@ sleep: | |||
1789 | __set_current_state(TASK_RUNNING); | 1799 | __set_current_state(TASK_RUNNING); |
1790 | } | 1800 | } |
1791 | } while (!kthread_should_stop()); | 1801 | } while (!kthread_should_stop()); |
1802 | |||
1803 | /* | ||
1804 | * Transaction kthread is stopped before us and wakes us up. | ||
1805 | * However we might have started a new transaction and COWed some | ||
1806 | * tree blocks when deleting unused block groups for example. So | ||
1807 | * make sure we commit the transaction we started to have a clean | ||
1808 | * shutdown when evicting the btree inode - if it has dirty pages | ||
1809 | * when we do the final iput() on it, eviction will trigger a | ||
1810 | * writeback for it which will fail with null pointer dereferences | ||
1811 | * since work queues and other resources were already released and | ||
1812 | * destroyed by the time the iput/eviction/writeback is made. | ||
1813 | */ | ||
1814 | trans = btrfs_attach_transaction(root); | ||
1815 | if (IS_ERR(trans)) { | ||
1816 | if (PTR_ERR(trans) != -ENOENT) | ||
1817 | btrfs_err(root->fs_info, | ||
1818 | "cleaner transaction attach returned %ld", | ||
1819 | PTR_ERR(trans)); | ||
1820 | } else { | ||
1821 | int ret; | ||
1822 | |||
1823 | ret = btrfs_commit_transaction(trans, root); | ||
1824 | if (ret) | ||
1825 | btrfs_err(root->fs_info, | ||
1826 | "cleaner open transaction commit returned %d", | ||
1827 | ret); | ||
1828 | } | ||
1829 | |||
1792 | return 0; | 1830 | return 0; |
1793 | } | 1831 | } |
1794 | 1832 | ||
@@ -2492,6 +2530,7 @@ int open_ctree(struct super_block *sb, | |||
2492 | spin_lock_init(&fs_info->unused_bgs_lock); | 2530 | spin_lock_init(&fs_info->unused_bgs_lock); |
2493 | rwlock_init(&fs_info->tree_mod_log_lock); | 2531 | rwlock_init(&fs_info->tree_mod_log_lock); |
2494 | mutex_init(&fs_info->unused_bg_unpin_mutex); | 2532 | mutex_init(&fs_info->unused_bg_unpin_mutex); |
2533 | mutex_init(&fs_info->delete_unused_bgs_mutex); | ||
2495 | mutex_init(&fs_info->reloc_mutex); | 2534 | mutex_init(&fs_info->reloc_mutex); |
2496 | mutex_init(&fs_info->delalloc_root_mutex); | 2535 | mutex_init(&fs_info->delalloc_root_mutex); |
2497 | seqlock_init(&fs_info->profiles_lock); | 2536 | seqlock_init(&fs_info->profiles_lock); |