diff options
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r-- | fs/btrfs/transaction.c | 56 |
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, | |||
948 | int btrfs_add_dead_root(struct btrfs_root *root) | 948 | int 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 | */ |
1878 | int btrfs_clean_old_snapshots(struct btrfs_root *root) | 1885 | int 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 | } |