Btrfs: fix race between fs trimming and block group remove/allocation
[linux-2.6-block.git] / fs / btrfs / disk-io.c
index 1e3e414c85017c8cbe39c19d90223cb25520e38a..30965120772bd2d814a97d9b4758f1bc0b8cfe6c 100644 (file)
@@ -2384,6 +2384,8 @@ int open_ctree(struct super_block *sb,
        init_waitqueue_head(&fs_info->transaction_blocked_wait);
        init_waitqueue_head(&fs_info->async_submit_wait);
 
+       INIT_LIST_HEAD(&fs_info->pinned_chunks);
+
        ret = btrfs_alloc_stripe_hash_table(fs_info);
        if (ret) {
                err = ret;
@@ -3715,6 +3717,17 @@ void close_ctree(struct btrfs_root *root)
 
        btrfs_free_block_rsv(root, root->orphan_block_rsv);
        root->orphan_block_rsv = NULL;
+
+       lock_chunks(root);
+       while (!list_empty(&fs_info->pinned_chunks)) {
+               struct extent_map *em;
+
+               em = list_first_entry(&fs_info->pinned_chunks,
+                                     struct extent_map, list);
+               list_del_init(&em->list);
+               free_extent_map(em);
+       }
+       unlock_chunks(root);
 }
 
 int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid,