aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/disk-io.c17
-rw-r--r--fs/btrfs/extent-tree.c8
-rw-r--r--fs/btrfs/relocation.c3
-rw-r--r--fs/btrfs/transaction.c56
-rw-r--r--fs/btrfs/transaction.h2
5 files changed, 57 insertions, 29 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 898263f56d96..b8ed1d4fe509 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1658,15 +1658,20 @@ static int cleaner_kthread(void *arg)
1658 struct btrfs_root *root = arg; 1658 struct btrfs_root *root = arg;
1659 1659
1660 do { 1660 do {
1661 int again = 0;
1662
1661 if (!(root->fs_info->sb->s_flags & MS_RDONLY) && 1663 if (!(root->fs_info->sb->s_flags & MS_RDONLY) &&
1662 mutex_trylock(&root->fs_info->cleaner_mutex)) { 1664 down_read_trylock(&root->fs_info->sb->s_umount)) {
1663 btrfs_run_delayed_iputs(root); 1665 if (mutex_trylock(&root->fs_info->cleaner_mutex)) {
1664 btrfs_clean_old_snapshots(root); 1666 btrfs_run_delayed_iputs(root);
1665 mutex_unlock(&root->fs_info->cleaner_mutex); 1667 again = btrfs_clean_one_deleted_snapshot(root);
1668 mutex_unlock(&root->fs_info->cleaner_mutex);
1669 }
1666 btrfs_run_defrag_inodes(root->fs_info); 1670 btrfs_run_defrag_inodes(root->fs_info);
1671 up_read(&root->fs_info->sb->s_umount);
1667 } 1672 }
1668 1673
1669 if (!try_to_freeze()) { 1674 if (!try_to_freeze() && !again) {
1670 set_current_state(TASK_INTERRUPTIBLE); 1675 set_current_state(TASK_INTERRUPTIBLE);
1671 if (!kthread_should_stop()) 1676 if (!kthread_should_stop())
1672 schedule(); 1677 schedule();
@@ -3358,8 +3363,8 @@ int btrfs_commit_super(struct btrfs_root *root)
3358 3363
3359 mutex_lock(&root->fs_info->cleaner_mutex); 3364 mutex_lock(&root->fs_info->cleaner_mutex);
3360 btrfs_run_delayed_iputs(root); 3365 btrfs_run_delayed_iputs(root);
3361 btrfs_clean_old_snapshots(root);
3362 mutex_unlock(&root->fs_info->cleaner_mutex); 3366 mutex_unlock(&root->fs_info->cleaner_mutex);
3367 wake_up_process(root->fs_info->cleaner_kthread);
3363 3368
3364 /* wait until ongoing cleanup work done */ 3369 /* wait until ongoing cleanup work done */
3365 down_write(&root->fs_info->cleanup_work_sem); 3370 down_write(&root->fs_info->cleanup_work_sem);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 7505856df9f3..be09157ff91b 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -7286,6 +7286,8 @@ static noinline int walk_up_tree(struct btrfs_trans_handle *trans,
7286 * reference count by one. if update_ref is true, this function 7286 * reference count by one. if update_ref is true, this function
7287 * also make sure backrefs for the shared block and all lower level 7287 * also make sure backrefs for the shared block and all lower level
7288 * blocks are properly updated. 7288 * blocks are properly updated.
7289 *
7290 * If called with for_reloc == 0, may exit early with -EAGAIN
7289 */ 7291 */
7290int btrfs_drop_snapshot(struct btrfs_root *root, 7292int btrfs_drop_snapshot(struct btrfs_root *root,
7291 struct btrfs_block_rsv *block_rsv, int update_ref, 7293 struct btrfs_block_rsv *block_rsv, int update_ref,
@@ -7386,6 +7388,12 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
7386 wc->reada_count = BTRFS_NODEPTRS_PER_BLOCK(root); 7388 wc->reada_count = BTRFS_NODEPTRS_PER_BLOCK(root);
7387 7389
7388 while (1) { 7390 while (1) {
7391 if (!for_reloc && btrfs_fs_closing(root->fs_info)) {
7392 pr_debug("btrfs: drop snapshot early exit\n");
7393 err = -EAGAIN;
7394 goto out_end_trans;
7395 }
7396
7389 ret = walk_down_tree(trans, root, path, wc); 7397 ret = walk_down_tree(trans, root, path, wc);
7390 if (ret < 0) { 7398 if (ret < 0) {
7391 err = ret; 7399 err = ret;
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 86f192ffc212..4ef5f7455fb3 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -4148,10 +4148,7 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start)
4148 4148
4149 while (1) { 4149 while (1) {
4150 mutex_lock(&fs_info->cleaner_mutex); 4150 mutex_lock(&fs_info->cleaner_mutex);
4151
4152 btrfs_clean_old_snapshots(fs_info->tree_root);
4153 ret = relocate_block_group(rc); 4151 ret = relocate_block_group(rc);
4154
4155 mutex_unlock(&fs_info->cleaner_mutex); 4152 mutex_unlock(&fs_info->cleaner_mutex);
4156 if (ret < 0) { 4153 if (ret < 0) {
4157 err = ret; 4154 err = ret;
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 6c0a72ab6de0..5a5ea99f29ed 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -948,7 +948,7 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans,
948int btrfs_add_dead_root(struct btrfs_root *root) 948int btrfs_add_dead_root(struct btrfs_root *root)
949{ 949{
950 spin_lock(&root->fs_info->trans_lock); 950 spin_lock(&root->fs_info->trans_lock);
951 list_add(&root->root_list, &root->fs_info->dead_roots); 951 list_add_tail(&root->root_list, &root->fs_info->dead_roots);
952 spin_unlock(&root->fs_info->trans_lock); 952 spin_unlock(&root->fs_info->trans_lock);
953 return 0; 953 return 0;
954} 954}
@@ -1873,31 +1873,49 @@ cleanup_transaction:
1873} 1873}
1874 1874
1875/* 1875/*
1876 * interface function to delete all the snapshots we have scheduled for deletion 1876 * return < 0 if error
1877 * 0 if there are no more dead_roots at the time of call
1878 * 1 there are more to be processed, call me again
1879 *
1880 * The return value indicates there are certainly more snapshots to delete, but
1881 * if there comes a new one during processing, it may return 0. We don't mind,
1882 * because btrfs_commit_super will poke cleaner thread and it will process it a
1883 * few seconds later.
1877 */ 1884 */
1878int btrfs_clean_old_snapshots(struct btrfs_root *root) 1885int btrfs_clean_one_deleted_snapshot(struct btrfs_root *root)
1879{ 1886{
1880 LIST_HEAD(list); 1887 int ret;
1881 struct btrfs_fs_info *fs_info = root->fs_info; 1888 struct btrfs_fs_info *fs_info = root->fs_info;
1882 1889
1890 if (fs_info->sb->s_flags & MS_RDONLY) {
1891 pr_debug("btrfs: cleaner called for RO fs!\n");
1892 return 0;
1893 }
1894
1883 spin_lock(&fs_info->trans_lock); 1895 spin_lock(&fs_info->trans_lock);
1884 list_splice_init(&fs_info->dead_roots, &list); 1896 if (list_empty(&fs_info->dead_roots)) {
1897 spin_unlock(&fs_info->trans_lock);
1898 return 0;
1899 }
1900 root = list_first_entry(&fs_info->dead_roots,
1901 struct btrfs_root, root_list);
1902 list_del(&root->root_list);
1885 spin_unlock(&fs_info->trans_lock); 1903 spin_unlock(&fs_info->trans_lock);
1886 1904
1887 while (!list_empty(&list)) { 1905 pr_debug("btrfs: cleaner removing %llu\n",
1888 int ret; 1906 (unsigned long long)root->objectid);
1889
1890 root = list_entry(list.next, struct btrfs_root, root_list);
1891 list_del(&root->root_list);
1892 1907
1893 btrfs_kill_all_delayed_nodes(root); 1908 btrfs_kill_all_delayed_nodes(root);
1894 1909
1895 if (btrfs_header_backref_rev(root->node) < 1910 if (btrfs_header_backref_rev(root->node) <
1896 BTRFS_MIXED_BACKREF_REV) 1911 BTRFS_MIXED_BACKREF_REV)
1897 ret = btrfs_drop_snapshot(root, NULL, 0, 0); 1912 ret = btrfs_drop_snapshot(root, NULL, 0, 0);
1898 else 1913 else
1899 ret =btrfs_drop_snapshot(root, NULL, 1, 0); 1914 ret = btrfs_drop_snapshot(root, NULL, 1, 0);
1900 BUG_ON(ret < 0); 1915 /*
1901 } 1916 * If we encounter a transaction abort during snapshot cleaning, we
1902 return 0; 1917 * don't want to crash here
1918 */
1919 BUG_ON(ret < 0 && ret != -EAGAIN && ret != -EROFS);
1920 return 1;
1903} 1921}
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index 3c8e0d25c8e4..f6edd5e6baa3 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -123,7 +123,7 @@ int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
123 123
124int btrfs_add_dead_root(struct btrfs_root *root); 124int btrfs_add_dead_root(struct btrfs_root *root);
125int btrfs_defrag_root(struct btrfs_root *root); 125int btrfs_defrag_root(struct btrfs_root *root);
126int btrfs_clean_old_snapshots(struct btrfs_root *root); 126int btrfs_clean_one_deleted_snapshot(struct btrfs_root *root);
127int btrfs_commit_transaction(struct btrfs_trans_handle *trans, 127int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
128 struct btrfs_root *root); 128 struct btrfs_root *root);
129int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans, 129int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans,