aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/transaction.c
diff options
context:
space:
mode:
authorDavid Sterba <dsterba@suse.cz>2013-03-12 11:13:28 -0400
committerJosef Bacik <jbacik@fusionio.com>2013-05-06 15:54:21 -0400
commit9d1a2a3ad59f7ae810bf04a5a05995bf2d79300c (patch)
tree1648c620a5264275004bd09c207292697b450367 /fs/btrfs/transaction.c
parent6841ebee6b02abe178abd30f40806e385cd96777 (diff)
btrfs: clean snapshots one by one
Each time pick one dead root from the list and let the caller know if it's needed to continue. This should improve responsiveness during umount and balance which at some point waits for cleaning all currently queued dead roots. A new dead root is added to the end of the list, so the snapshots disappear in the order of deletion. The snapshot cleaning work is now done only from the cleaner thread and the others wake it if needed. Signed-off-by: David Sterba <dsterba@suse.cz> Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r--fs/btrfs/transaction.c56
1 files changed, 37 insertions, 19 deletions
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}