btrfs: clean snapshots one by one
[firefly-linux-kernel-4.4.55.git] / fs / btrfs / disk-io.c
index 6d19a0a554aadc3aeadbe1df6eff03acd489375e..b8ed1d4fe50966142e01945799046835b5f256ec 100644 (file)
@@ -238,7 +238,7 @@ out:
        return em;
 }
 
-u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len)
+u32 btrfs_csum_data(char *data, u32 seed, size_t len)
 {
        return crc32c(seed, data, len);
 }
@@ -274,7 +274,7 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
                if (err)
                        return 1;
                cur_len = min(len, map_len - (offset - map_start));
-               crc = btrfs_csum_data(root, kaddr + offset - map_start,
+               crc = btrfs_csum_data(kaddr + offset - map_start,
                                      crc, cur_len);
                len -= cur_len;
                offset += cur_len;
@@ -1658,15 +1658,20 @@ static int cleaner_kthread(void *arg)
        struct btrfs_root *root = arg;
 
        do {
+               int again = 0;
+
                if (!(root->fs_info->sb->s_flags & MS_RDONLY) &&
-                   mutex_trylock(&root->fs_info->cleaner_mutex)) {
-                       btrfs_run_delayed_iputs(root);
-                       btrfs_clean_old_snapshots(root);
-                       mutex_unlock(&root->fs_info->cleaner_mutex);
+                   down_read_trylock(&root->fs_info->sb->s_umount)) {
+                       if (mutex_trylock(&root->fs_info->cleaner_mutex)) {
+                               btrfs_run_delayed_iputs(root);
+                               again = btrfs_clean_one_deleted_snapshot(root);
+                               mutex_unlock(&root->fs_info->cleaner_mutex);
+                       }
                        btrfs_run_defrag_inodes(root->fs_info);
+                       up_read(&root->fs_info->sb->s_umount);
                }
 
-               if (!try_to_freeze()) {
+               if (!try_to_freeze() && !again) {
                        set_current_state(TASK_INTERRUPTIBLE);
                        if (!kthread_should_stop())
                                schedule();
@@ -1935,6 +1940,27 @@ static noinline int next_root_backup(struct btrfs_fs_info *info,
        return 0;
 }
 
+/* helper to cleanup workers */
+static void btrfs_stop_all_workers(struct btrfs_fs_info *fs_info)
+{
+       btrfs_stop_workers(&fs_info->generic_worker);
+       btrfs_stop_workers(&fs_info->fixup_workers);
+       btrfs_stop_workers(&fs_info->delalloc_workers);
+       btrfs_stop_workers(&fs_info->workers);
+       btrfs_stop_workers(&fs_info->endio_workers);
+       btrfs_stop_workers(&fs_info->endio_meta_workers);
+       btrfs_stop_workers(&fs_info->endio_raid56_workers);
+       btrfs_stop_workers(&fs_info->rmw_workers);
+       btrfs_stop_workers(&fs_info->endio_meta_write_workers);
+       btrfs_stop_workers(&fs_info->endio_write_workers);
+       btrfs_stop_workers(&fs_info->endio_freespace_worker);
+       btrfs_stop_workers(&fs_info->submit_workers);
+       btrfs_stop_workers(&fs_info->delayed_workers);
+       btrfs_stop_workers(&fs_info->caching_workers);
+       btrfs_stop_workers(&fs_info->readahead_workers);
+       btrfs_stop_workers(&fs_info->flush_workers);
+}
+
 /* helper to cleanup tree roots */
 static void free_root_pointers(struct btrfs_fs_info *info, int chunk_root)
 {
@@ -2290,6 +2316,9 @@ int open_ctree(struct super_block *sb,
        if (tree_root->fs_info->compress_type == BTRFS_COMPRESS_LZO)
                features |= BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO;
 
+       if (features & BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA)
+               printk(KERN_ERR "btrfs: has skinny extents\n");
+
        /*
         * flag our filesystem as having big metadata blocks if
         * they are bigger than the page size
@@ -2757,22 +2786,7 @@ fail_tree_roots:
        invalidate_inode_pages2(fs_info->btree_inode->i_mapping);
 
 fail_sb_buffer:
-       btrfs_stop_workers(&fs_info->generic_worker);
-       btrfs_stop_workers(&fs_info->readahead_workers);
-       btrfs_stop_workers(&fs_info->fixup_workers);
-       btrfs_stop_workers(&fs_info->delalloc_workers);
-       btrfs_stop_workers(&fs_info->workers);
-       btrfs_stop_workers(&fs_info->endio_workers);
-       btrfs_stop_workers(&fs_info->endio_meta_workers);
-       btrfs_stop_workers(&fs_info->endio_raid56_workers);
-       btrfs_stop_workers(&fs_info->rmw_workers);
-       btrfs_stop_workers(&fs_info->endio_meta_write_workers);
-       btrfs_stop_workers(&fs_info->endio_write_workers);
-       btrfs_stop_workers(&fs_info->endio_freespace_worker);
-       btrfs_stop_workers(&fs_info->submit_workers);
-       btrfs_stop_workers(&fs_info->delayed_workers);
-       btrfs_stop_workers(&fs_info->caching_workers);
-       btrfs_stop_workers(&fs_info->flush_workers);
+       btrfs_stop_all_workers(fs_info);
 fail_alloc:
 fail_iput:
        btrfs_mapping_tree_free(&fs_info->mapping_tree);
@@ -2919,7 +2933,7 @@ static int write_dev_supers(struct btrfs_device *device,
                        btrfs_set_super_bytenr(sb, bytenr);
 
                        crc = ~(u32)0;
-                       crc = btrfs_csum_data(NULL, (char *)sb +
+                       crc = btrfs_csum_data((char *)sb +
                                              BTRFS_CSUM_SIZE, crc,
                                              BTRFS_SUPER_INFO_SIZE -
                                              BTRFS_CSUM_SIZE);
@@ -3349,8 +3363,8 @@ int btrfs_commit_super(struct btrfs_root *root)
 
        mutex_lock(&root->fs_info->cleaner_mutex);
        btrfs_run_delayed_iputs(root);
-       btrfs_clean_old_snapshots(root);
        mutex_unlock(&root->fs_info->cleaner_mutex);
+       wake_up_process(root->fs_info->cleaner_kthread);
 
        /* wait until ongoing cleanup work done */
        down_write(&root->fs_info->cleanup_work_sem);
@@ -3426,20 +3440,7 @@ int close_ctree(struct btrfs_root *root)
                       percpu_counter_sum(&fs_info->delalloc_bytes));
        }
 
-       free_extent_buffer(fs_info->extent_root->node);
-       free_extent_buffer(fs_info->extent_root->commit_root);
-       free_extent_buffer(fs_info->tree_root->node);
-       free_extent_buffer(fs_info->tree_root->commit_root);
-       free_extent_buffer(fs_info->chunk_root->node);
-       free_extent_buffer(fs_info->chunk_root->commit_root);
-       free_extent_buffer(fs_info->dev_root->node);
-       free_extent_buffer(fs_info->dev_root->commit_root);
-       free_extent_buffer(fs_info->csum_root->node);
-       free_extent_buffer(fs_info->csum_root->commit_root);
-       if (fs_info->quota_root) {
-               free_extent_buffer(fs_info->quota_root->node);
-               free_extent_buffer(fs_info->quota_root->commit_root);
-       }
+       free_root_pointers(fs_info, 1);
 
        btrfs_free_block_groups(fs_info);
 
@@ -3447,22 +3448,7 @@ int close_ctree(struct btrfs_root *root)
 
        iput(fs_info->btree_inode);
 
-       btrfs_stop_workers(&fs_info->generic_worker);
-       btrfs_stop_workers(&fs_info->fixup_workers);
-       btrfs_stop_workers(&fs_info->delalloc_workers);
-       btrfs_stop_workers(&fs_info->workers);
-       btrfs_stop_workers(&fs_info->endio_workers);
-       btrfs_stop_workers(&fs_info->endio_meta_workers);
-       btrfs_stop_workers(&fs_info->endio_raid56_workers);
-       btrfs_stop_workers(&fs_info->rmw_workers);
-       btrfs_stop_workers(&fs_info->endio_meta_write_workers);
-       btrfs_stop_workers(&fs_info->endio_write_workers);
-       btrfs_stop_workers(&fs_info->endio_freespace_worker);
-       btrfs_stop_workers(&fs_info->submit_workers);
-       btrfs_stop_workers(&fs_info->delayed_workers);
-       btrfs_stop_workers(&fs_info->caching_workers);
-       btrfs_stop_workers(&fs_info->readahead_workers);
-       btrfs_stop_workers(&fs_info->flush_workers);
+       btrfs_stop_all_workers(fs_info);
 
 #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
        if (btrfs_test_opt(root, CHECK_INTEGRITY))