Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 20 Dec 2014 02:10:42 +0000 (18:10 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 20 Dec 2014 02:10:42 +0000 (18:10 -0800)
Pull more btrfs updates from Chris Mason:
 "This is part two of our merge window patches.

  These are all from Filipe, and fix some really hard to find races that
  can cause corruptions.  Most of them involved block group removal
  (balance) or discard"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs:
  Btrfs: remove non-sense btrfs_error_discard_extent() function
  Btrfs: fix fs corruption on transaction abort if device supports discard
  Btrfs: always clear a block group node when removing it from the tree
  Btrfs: ensure deletion from pinned_chunks list is protected

fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/free-space-cache.c

index e6fbbd74b716ae69da265779af5317c0057f1a18..7e607416755a880fef1a06d3a8a3482417c0b364 100644 (file)
@@ -3481,8 +3481,8 @@ void btrfs_put_block_group_cache(struct btrfs_fs_info *info);
 u64 btrfs_account_ro_block_groups_free_space(struct btrfs_space_info *sinfo);
 int btrfs_error_unpin_extent_range(struct btrfs_root *root,
                                   u64 start, u64 end);
-int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr,
-                              u64 num_bytes, u64 *actual_bytes);
+int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
+                        u64 num_bytes, u64 *actual_bytes);
 int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans,
                            struct btrfs_root *root, u64 type);
 int btrfs_trim_fs(struct btrfs_root *root, struct fstrim_range *range);
index 30965120772bd2d814a97d9b4758f1bc0b8cfe6c..8c63419a7f70de04d2e5fd1a51a3a0e334513918 100644 (file)
@@ -4121,12 +4121,6 @@ again:
                if (ret)
                        break;
 
-               /* opt_discard */
-               if (btrfs_test_opt(root, DISCARD))
-                       ret = btrfs_error_discard_extent(root, start,
-                                                        end + 1 - start,
-                                                        NULL);
-
                clear_extent_dirty(unpin, start, end, GFP_NOFS);
                btrfs_error_unpin_extent_range(root, start, end);
                cond_resched();
index 222d6aea4a8a778cff8386873d8cb51ed5f86b16..a80b97100d90b3162d7d3688ed6b3c459bb56bc8 100644 (file)
@@ -1889,8 +1889,8 @@ static int btrfs_issue_discard(struct block_device *bdev,
        return blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_NOFS, 0);
 }
 
-static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
-                               u64 num_bytes, u64 *actual_bytes)
+int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
+                        u64 num_bytes, u64 *actual_bytes)
 {
        int ret;
        u64 discarded_bytes = 0;
@@ -5727,7 +5727,8 @@ void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans,
        update_global_block_rsv(fs_info);
 }
 
-static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end)
+static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end,
+                             const bool return_free_space)
 {
        struct btrfs_fs_info *fs_info = root->fs_info;
        struct btrfs_block_group_cache *cache = NULL;
@@ -5751,7 +5752,8 @@ static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end)
 
                if (start < cache->last_byte_to_unpin) {
                        len = min(len, cache->last_byte_to_unpin - start);
-                       btrfs_add_free_space(cache, start, len);
+                       if (return_free_space)
+                               btrfs_add_free_space(cache, start, len);
                }
 
                start += len;
@@ -5815,7 +5817,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans,
                                                   end + 1 - start, NULL);
 
                clear_extent_dirty(unpin, start, end, GFP_NOFS);
-               unpin_extent_range(root, start, end);
+               unpin_extent_range(root, start, end, true);
                cond_resched();
        }
 
@@ -8872,6 +8874,7 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
                                       cache_node);
                rb_erase(&block_group->cache_node,
                         &info->block_group_cache_tree);
+               RB_CLEAR_NODE(&block_group->cache_node);
                spin_unlock(&info->block_group_cache_lock);
 
                down_write(&block_group->space_info->groups_sem);
@@ -9130,6 +9133,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
                        spin_lock(&info->block_group_cache_lock);
                        rb_erase(&cache->cache_node,
                                 &info->block_group_cache_tree);
+                       RB_CLEAR_NODE(&cache->cache_node);
                        spin_unlock(&info->block_group_cache_lock);
                        btrfs_put_block_group(cache);
                        goto error;
@@ -9271,6 +9275,7 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
                spin_lock(&root->fs_info->block_group_cache_lock);
                rb_erase(&cache->cache_node,
                         &root->fs_info->block_group_cache_tree);
+               RB_CLEAR_NODE(&cache->cache_node);
                spin_unlock(&root->fs_info->block_group_cache_lock);
                btrfs_put_block_group(cache);
                return ret;
@@ -9690,13 +9695,7 @@ out:
 
 int btrfs_error_unpin_extent_range(struct btrfs_root *root, u64 start, u64 end)
 {
-       return unpin_extent_range(root, start, end);
-}
-
-int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr,
-                              u64 num_bytes, u64 *actual_bytes)
-{
-       return btrfs_discard_extent(root, bytenr, num_bytes, actual_bytes);
+       return unpin_extent_range(root, start, end, false);
 }
 
 int btrfs_trim_fs(struct btrfs_root *root, struct fstrim_range *range)
index 030847bf7cec803e36485e0999b7309d941877ef..d6c03f7f136b359c534668a38f9e9a72d299eb66 100644 (file)
@@ -2966,8 +2966,8 @@ static int do_trimming(struct btrfs_block_group_cache *block_group,
        spin_unlock(&block_group->lock);
        spin_unlock(&space_info->lock);
 
-       ret = btrfs_error_discard_extent(fs_info->extent_root,
-                                        start, bytes, &trimmed);
+       ret = btrfs_discard_extent(fs_info->extent_root,
+                                  start, bytes, &trimmed);
        if (!ret)
                *total_trimmed += trimmed;
 
@@ -3185,16 +3185,18 @@ out:
 
                spin_unlock(&block_group->lock);
 
+               lock_chunks(block_group->fs_info->chunk_root);
                em_tree = &block_group->fs_info->mapping_tree.map_tree;
                write_lock(&em_tree->lock);
                em = lookup_extent_mapping(em_tree, block_group->key.objectid,
                                           1);
                BUG_ON(!em); /* logic error, can't happen */
+               /*
+                * remove_extent_mapping() will delete us from the pinned_chunks
+                * list, which is protected by the chunk mutex.
+                */
                remove_extent_mapping(em_tree, em);
                write_unlock(&em_tree->lock);
-
-               lock_chunks(block_group->fs_info->chunk_root);
-               list_del_init(&em->list);
                unlock_chunks(block_group->fs_info->chunk_root);
 
                /* once for us and once for the tree */