]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - fs/btrfs/disk-io.c
Merge tag 'pm-5.6-rc1-3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
[linux.git] / fs / btrfs / disk-io.c
index e0edfdc9c82bea289b88d320e98147b7a88ef4bf..7fa9bb79ad08e2c5b732185c902bcbbea549a95f 100644 (file)
@@ -41,6 +41,7 @@
 #include "tree-checker.h"
 #include "ref-verify.h"
 #include "block-group.h"
+#include "discard.h"
 
 #define BTRFS_SUPER_FLAG_SUPP  (BTRFS_HEADER_FLAG_WRITTEN |\
                                 BTRFS_HEADER_FLAG_RELOC |\
@@ -202,8 +203,8 @@ void btrfs_set_buffer_lockdep_class(u64 objectid, struct extent_buffer *eb,
  * that covers the entire device
  */
 struct extent_map *btree_get_extent(struct btrfs_inode *inode,
-               struct page *page, size_t pg_offset, u64 start, u64 len,
-               int create)
+                                   struct page *page, size_t pg_offset,
+                                   u64 start, u64 len)
 {
        struct extent_map_tree *em_tree = &inode->extent_tree;
        struct extent_map *em;
@@ -1953,6 +1954,8 @@ static void btrfs_stop_all_workers(struct btrfs_fs_info *fs_info)
        btrfs_destroy_workqueue(fs_info->readahead_workers);
        btrfs_destroy_workqueue(fs_info->flush_workers);
        btrfs_destroy_workqueue(fs_info->qgroup_rescan_workers);
+       if (fs_info->discard_ctl.discard_workers)
+               destroy_workqueue(fs_info->discard_ctl.discard_workers);
        /*
         * Now that all other work queues are destroyed, we can safely destroy
         * the queues used for metadata I/O, since tasks from those other work
@@ -2148,6 +2151,8 @@ static int btrfs_init_workqueues(struct btrfs_fs_info *fs_info,
                                      max_active, 2);
        fs_info->qgroup_rescan_workers =
                btrfs_alloc_workqueue(fs_info, "qgroup-rescan", flags, 1, 0);
+       fs_info->discard_ctl.discard_workers =
+               alloc_workqueue("btrfs_discard", WQ_UNBOUND | WQ_FREEZABLE, 1);
 
        if (!(fs_info->workers && fs_info->delalloc_workers &&
              fs_info->flush_workers &&
@@ -2158,7 +2163,8 @@ static int btrfs_init_workqueues(struct btrfs_fs_info *fs_info,
              fs_info->endio_freespace_worker && fs_info->rmw_workers &&
              fs_info->caching_workers && fs_info->readahead_workers &&
              fs_info->fixup_workers && fs_info->delayed_workers &&
-             fs_info->qgroup_rescan_workers)) {
+             fs_info->qgroup_rescan_workers &&
+             fs_info->discard_ctl.discard_workers)) {
                return -ENOMEM;
        }
 
@@ -2691,7 +2697,6 @@ int __cold open_ctree(struct super_block *sb,
        spin_lock_init(&fs_info->fs_roots_radix_lock);
        spin_lock_init(&fs_info->delayed_iput_lock);
        spin_lock_init(&fs_info->defrag_inodes_lock);
-       spin_lock_init(&fs_info->tree_mod_seq_lock);
        spin_lock_init(&fs_info->super_lock);
        spin_lock_init(&fs_info->buffer_lock);
        spin_lock_init(&fs_info->unused_bgs_lock);
@@ -2792,6 +2797,7 @@ int __cold open_ctree(struct super_block *sb,
 
        btrfs_init_dev_replace_locks(fs_info);
        btrfs_init_qgroup(fs_info);
+       btrfs_discard_init(fs_info);
 
        btrfs_init_free_cluster(&fs_info->meta_alloc_cluster);
        btrfs_init_free_cluster(&fs_info->data_alloc_cluster);
@@ -3082,20 +3088,13 @@ int __cold open_ctree(struct super_block *sb,
 
        btrfs_free_extra_devids(fs_devices, 1);
 
-       ret = btrfs_sysfs_add_fsid(fs_devices, NULL);
+       ret = btrfs_sysfs_add_fsid(fs_devices);
        if (ret) {
                btrfs_err(fs_info, "failed to init sysfs fsid interface: %d",
                                ret);
                goto fail_block_groups;
        }
 
-       ret = btrfs_sysfs_add_device(fs_devices);
-       if (ret) {
-               btrfs_err(fs_info, "failed to init sysfs device interface: %d",
-                               ret);
-               goto fail_fsdev_sysfs;
-       }
-
        ret = btrfs_sysfs_add_mounted(fs_info);
        if (ret) {
                btrfs_err(fs_info, "failed to init sysfs interface: %d", ret);
@@ -3262,6 +3261,7 @@ int __cold open_ctree(struct super_block *sb,
        }
 
        btrfs_qgroup_rescan_resume(fs_info);
+       btrfs_discard_resume(fs_info);
 
        if (!fs_info->uuid_root) {
                btrfs_info(fs_info, "creating UUID tree");
@@ -3978,6 +3978,9 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
 
        cancel_work_sync(&fs_info->async_reclaim_work);
 
+       /* Cancel or finish ongoing discard work */
+       btrfs_discard_cleanup(fs_info);
+
        if (!sb_rdonly(fs_info->sb)) {
                /*
                 * The cleaner kthread is stopped, so do one final pass over
@@ -4026,11 +4029,18 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
        invalidate_inode_pages2(fs_info->btree_inode->i_mapping);
        btrfs_stop_all_workers(fs_info);
 
-       btrfs_free_block_groups(fs_info);
-
        clear_bit(BTRFS_FS_OPEN, &fs_info->flags);
        free_root_pointers(fs_info, true);
 
+       /*
+        * We must free the block groups after dropping the fs_roots as we could
+        * have had an IO error and have left over tree log blocks that aren't
+        * cleaned up until the fs roots are freed.  This makes the block group
+        * accounting appear to be wrong because there's pending reserved bytes,
+        * so make sure we do the block group cleanup afterwards.
+        */
+       btrfs_free_block_groups(fs_info);
+
        iput(fs_info->btree_inode);
 
 #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY