aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/transaction.c
diff options
context:
space:
mode:
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}