#ifdef CONFIG_BTRFS_DEBUG
        struct kobject *debug_kobj;
        struct kobject *discard_debug_kobj;
+       struct list_head allocated_roots;
 #endif
 };
 
 #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
        u64 alloc_bytenr;
 #endif
+
+#ifdef CONFIG_BTRFS_DEBUG
+       struct list_head leak_list;
+#endif
 };
 
 struct btrfs_clone_extent_info {
 
 
        spin_lock_init(&root->root_item_lock);
        btrfs_qgroup_init_swapped_blocks(&root->swapped_blocks);
+#ifdef CONFIG_BTRFS_DEBUG
+       INIT_LIST_HEAD(&root->leak_list);
+       spin_lock(&fs_info->fs_roots_radix_lock);
+       list_add_tail(&root->leak_list, &fs_info->allocated_roots);
+       spin_unlock(&fs_info->fs_roots_radix_lock);
+#endif
 }
 
 static struct btrfs_root *btrfs_alloc_root(struct btrfs_fs_info *fs_info,
        return ret;
 }
 
+void btrfs_check_leaked_roots(struct btrfs_fs_info *fs_info)
+{
+#ifdef CONFIG_BTRFS_DEBUG
+       struct btrfs_root *root;
+
+       while (!list_empty(&fs_info->allocated_roots)) {
+               root = list_first_entry(&fs_info->allocated_roots,
+                                       struct btrfs_root, leak_list);
+               btrfs_err(fs_info, "leaked root %llu-%llu refcount %d",
+                         root->root_key.objectid, root->root_key.offset,
+                         refcount_read(&root->refs));
+               while (refcount_read(&root->refs) > 1)
+                       btrfs_put_fs_root(root);
+               btrfs_put_fs_root(root);
+       }
+#endif
+}
+
 void btrfs_free_fs_info(struct btrfs_fs_info *fs_info)
 {
        percpu_counter_destroy(&fs_info->dirty_metadata_bytes);
        btrfs_put_fs_root(fs_info->uuid_root);
        btrfs_put_fs_root(fs_info->free_space_root);
        btrfs_put_fs_root(fs_info->fs_root);
+       btrfs_check_leaked_roots(fs_info);
        kfree(fs_info->super_copy);
        kfree(fs_info->super_for_commit);
        kvfree(fs_info);
        INIT_LIST_HEAD(&fs_info->space_info);
        INIT_LIST_HEAD(&fs_info->tree_mod_seq_list);
        INIT_LIST_HEAD(&fs_info->unused_bgs);
+#ifdef CONFIG_BTRFS_DEBUG
+       INIT_LIST_HEAD(&fs_info->allocated_roots);
+#endif
        extent_map_tree_init(&fs_info->mapping_tree);
        btrfs_init_block_rsv(&fs_info->global_block_rsv,
                             BTRFS_BLOCK_RSV_GLOBAL);
 
 struct btrfs_device;
 struct btrfs_fs_devices;
 
+void btrfs_check_leaked_roots(struct btrfs_fs_info *fs_info);
 void btrfs_init_fs_info(struct btrfs_fs_info *fs_info);
 int btrfs_verify_level_key(struct extent_buffer *eb, int level,
                           struct btrfs_key *first_key, u64 parent_transid);
 {
        if (!root)
                return;
-       if (refcount_dec_and_test(&root->refs))
+       if (refcount_dec_and_test(&root->refs)) {
+#ifdef CONFIG_BTRFS_DEBUG
+               spin_lock(&root->fs_info->fs_roots_radix_lock);
+               list_del_init(&root->leak_list);
+               spin_unlock(&root->fs_info->fs_roots_radix_lock);
+#endif
                kfree(root);
+       }
 }
 
 void btrfs_mark_buffer_dirty(struct extent_buffer *buf);