Revert "btrfs: let btrfs_delete_unused_bgs() to clean relocated bgs"
[cascardo/linux.git] / fs / btrfs / extent-tree.c
index 38c2df8..210c94a 100644 (file)
@@ -87,7 +87,8 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
                          int force);
 static int find_next_key(struct btrfs_path *path, int level,
                         struct btrfs_key *key);
-static void dump_space_info(struct btrfs_space_info *info, u64 bytes,
+static void dump_space_info(struct btrfs_fs_info *fs_info,
+                           struct btrfs_space_info *info, u64 bytes,
                            int dump_block_groups);
 static int btrfs_add_reserved_bytes(struct btrfs_block_group_cache *cache,
                                    u64 ram_bytes, u64 num_bytes, int delalloc);
@@ -266,9 +267,8 @@ static int exclude_super_stripes(struct btrfs_root *root,
 
        for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
                bytenr = btrfs_sb_offset(i);
-               ret = btrfs_rmap_block(&root->fs_info->mapping_tree,
-                                      cache->key.objectid, bytenr,
-                                      0, &logical, &nr, &stripe_len);
+               ret = btrfs_rmap_block(root->fs_info, cache->key.objectid,
+                                      bytenr, 0, &logical, &nr, &stripe_len);
                if (ret)
                        return ret;
 
@@ -730,11 +730,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
 static struct btrfs_block_group_cache *
 btrfs_lookup_first_block_group(struct btrfs_fs_info *info, u64 bytenr)
 {
-       struct btrfs_block_group_cache *cache;
-
-       cache = block_group_cache_tree_search(info, bytenr, 0);
-
-       return cache;
+       return block_group_cache_tree_search(info, bytenr, 0);
 }
 
 /*
@@ -744,11 +740,7 @@ struct btrfs_block_group_cache *btrfs_lookup_block_group(
                                                 struct btrfs_fs_info *info,
                                                 u64 bytenr)
 {
-       struct btrfs_block_group_cache *cache;
-
-       cache = block_group_cache_tree_search(info, bytenr, 1);
-
-       return cache;
+       return block_group_cache_tree_search(info, bytenr, 1);
 }
 
 static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info,
@@ -2360,7 +2352,13 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans,
                ins.type = BTRFS_EXTENT_ITEM_KEY;
        }
 
-       BUG_ON(node->ref_mod != 1);
+       if (node->ref_mod != 1) {
+               btrfs_err(root->fs_info,
+       "btree block(%llu) has %d references rather than 1: action %d ref_root %llu parent %llu",
+                         node->bytenr, node->ref_mod, node->action, ref_root,
+                         parent);
+               return -EIO;
+       }
        if (node->action == BTRFS_ADD_DELAYED_REF && insert_reserved) {
                BUG_ON(!extent_op || !extent_op->update_flags);
                ret = alloc_reserved_tree_block(trans, root,
@@ -2590,7 +2588,9 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
                                        if (must_insert_reserved)
                                                locked_ref->must_insert_reserved = 1;
                                        locked_ref->processing = 0;
-                                       btrfs_debug(fs_info, "run_delayed_extent_op returned %d", ret);
+                                       btrfs_debug(fs_info,
+                                                   "run_delayed_extent_op returned %d",
+                                                   ret);
                                        btrfs_delayed_ref_unlock(locked_ref);
                                        return ret;
                                }
@@ -2650,7 +2650,8 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
                        locked_ref->processing = 0;
                        btrfs_delayed_ref_unlock(locked_ref);
                        btrfs_put_delayed_ref(ref);
-                       btrfs_debug(fs_info, "run_one_delayed_ref returned %d", ret);
+                       btrfs_debug(fs_info, "run_one_delayed_ref returned %d",
+                                   ret);
                        return ret;
                }
 
@@ -2940,7 +2941,7 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
        if (trans->aborted)
                return 0;
 
-       if (root->fs_info->creating_free_space_tree)
+       if (test_bit(BTRFS_FS_CREATING_FREE_SPACE_TREE, &root->fs_info->flags))
                return 0;
 
        if (root == root->fs_info->extent_root)
@@ -2971,7 +2972,6 @@ again:
                        spin_unlock(&delayed_refs->lock);
                        goto out;
                }
-               count = (unsigned long)-1;
 
                while (node) {
                        head = rb_entry(node, struct btrfs_delayed_ref_head,
@@ -3694,6 +3694,8 @@ again:
                        goto again;
                }
                spin_unlock(&cur_trans->dirty_bgs_lock);
+       } else if (ret < 0) {
+               btrfs_cleanup_dirty_bgs(cur_trans, root);
        }
 
        btrfs_free_path(path);
@@ -4271,13 +4273,10 @@ int btrfs_check_data_free_space(struct inode *inode, u64 start, u64 len)
        if (ret < 0)
                return ret;
 
-       /*
-        * Use new btrfs_qgroup_reserve_data to reserve precious data space
-        *
-        * TODO: Find a good method to avoid reserve data space for NOCOW
-        * range, but don't impact performance on quota disable case.
-        */
+       /* Use new btrfs_qgroup_reserve_data to reserve precious data space. */
        ret = btrfs_qgroup_reserve_data(inode, start, len);
+       if (ret)
+               btrfs_free_reserved_data_space_noquota(inode, start, len);
        return ret;
 }
 
@@ -4432,7 +4431,7 @@ void check_system_chunk(struct btrfs_trans_handle *trans,
        if (left < thresh && btrfs_test_opt(root->fs_info, ENOSPC_DEBUG)) {
                btrfs_info(root->fs_info, "left=%llu, need=%llu, flags=%llu",
                        left, thresh, type);
-               dump_space_info(info, 0, 0);
+               dump_space_info(root->fs_info, info, 0, 0);
        }
 
        if (left < thresh) {
@@ -5189,7 +5188,7 @@ static int __reserve_metadata_bytes(struct btrfs_root *root,
                 * which means we won't have fs_info->fs_root set, so don't do
                 * the async reclaim as we will panic.
                 */
-               if (!root->fs_info->log_root_recovering &&
+               if (!test_bit(BTRFS_FS_LOG_RECOVERING, &root->fs_info->flags) &&
                    need_do_async_reclaim(space_info, root, used) &&
                    !work_busy(&root->fs_info->async_reclaim_work)) {
                        trace_btrfs_trigger_flush(root->fs_info,
@@ -5795,7 +5794,7 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
        int ret;
        struct btrfs_block_rsv *global_rsv = &root->fs_info->global_block_rsv;
 
-       if (root->fs_info->quota_enabled) {
+       if (test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags)) {
                /* One for parent inode, two for dir entries */
                num_bytes = 3 * root->nodesize;
                ret = btrfs_qgroup_reserve_meta(root, num_bytes);
@@ -5973,7 +5972,7 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
        csum_bytes = BTRFS_I(inode)->csum_bytes;
        spin_unlock(&BTRFS_I(inode)->lock);
 
-       if (root->fs_info->quota_enabled) {
+       if (test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags)) {
                ret = btrfs_qgroup_reserve_meta(root,
                                nr_extents * root->nodesize);
                if (ret)
@@ -6113,8 +6112,6 @@ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes)
  * @start: start range we are writing to
  * @len: how long the range we are writing to
  *
- * TODO: This function will finally replace old btrfs_delalloc_reserve_space()
- *
  * This will do the following things
  *
  * o reserve space in data space info for num bytes
@@ -6933,8 +6930,9 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
                        }
 
                        if (ret) {
-                               btrfs_err(info, "umm, got %d back from search, was looking for %llu",
-                                       ret, bytenr);
+                               btrfs_err(info,
+                                         "umm, got %d back from search, was looking for %llu",
+                                         ret, bytenr);
                                if (ret > 0)
                                        btrfs_print_leaf(extent_root,
                                                         path->nodes[0]);
@@ -6980,7 +6978,8 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
                ret = btrfs_search_slot(trans, extent_root, &key, path,
                                        -1, 1);
                if (ret) {
-                       btrfs_err(info, "umm, got %d back from search, was looking for %llu",
+                       btrfs_err(info,
+                                 "umm, got %d back from search, was looking for %llu",
                                ret, bytenr);
                        btrfs_print_leaf(extent_root, path->nodes[0]);
                }
@@ -7007,8 +7006,9 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
 
        refs = btrfs_extent_refs(leaf, ei);
        if (refs < refs_to_drop) {
-               btrfs_err(info, "trying to drop %d refs but we only have %Lu "
-                         "for bytenr %Lu", refs_to_drop, refs, bytenr);
+               btrfs_err(info,
+                         "trying to drop %d refs but we only have %Lu for bytenr %Lu",
+                         refs_to_drop, refs, bytenr);
                ret = -EINVAL;
                btrfs_abort_transaction(trans, ret);
                goto out;
@@ -7904,23 +7904,24 @@ out:
        return ret;
 }
 
-static void dump_space_info(struct btrfs_space_info *info, u64 bytes,
+static void dump_space_info(struct btrfs_fs_info *fs_info,
+                           struct btrfs_space_info *info, u64 bytes,
                            int dump_block_groups)
 {
        struct btrfs_block_group_cache *cache;
        int index = 0;
 
        spin_lock(&info->lock);
-       printk(KERN_INFO "BTRFS: space_info %llu has %llu free, is %sfull\n",
-              info->flags,
-              info->total_bytes - info->bytes_used - info->bytes_pinned -
-              info->bytes_reserved - info->bytes_readonly -
-              info->bytes_may_use, (info->full) ? "" : "not ");
-       printk(KERN_INFO "BTRFS: space_info total=%llu, used=%llu, pinned=%llu, "
-              "reserved=%llu, may_use=%llu, readonly=%llu\n",
-              info->total_bytes, info->bytes_used, info->bytes_pinned,
-              info->bytes_reserved, info->bytes_may_use,
-              info->bytes_readonly);
+       btrfs_info(fs_info, "space_info %llu has %llu free, is %sfull",
+                  info->flags,
+                  info->total_bytes - info->bytes_used - info->bytes_pinned -
+                  info->bytes_reserved - info->bytes_readonly -
+                  info->bytes_may_use, (info->full) ? "" : "not ");
+       btrfs_info(fs_info,
+               "space_info total=%llu, used=%llu, pinned=%llu, reserved=%llu, may_use=%llu, readonly=%llu",
+               info->total_bytes, info->bytes_used, info->bytes_pinned,
+               info->bytes_reserved, info->bytes_may_use,
+               info->bytes_readonly);
        spin_unlock(&info->lock);
 
        if (!dump_block_groups)
@@ -7930,12 +7931,11 @@ static void dump_space_info(struct btrfs_space_info *info, u64 bytes,
 again:
        list_for_each_entry(cache, &info->block_groups[index], list) {
                spin_lock(&cache->lock);
-               printk(KERN_INFO "BTRFS: "
-                          "block group %llu has %llu bytes, "
-                          "%llu used %llu pinned %llu reserved %s\n",
-                      cache->key.objectid, cache->key.offset,
-                      btrfs_block_group_used(&cache->item), cache->pinned,
-                      cache->reserved, cache->ro ? "[readonly]" : "");
+               btrfs_info(fs_info,
+                       "block group %llu has %llu bytes, %llu used %llu pinned %llu reserved %s",
+                       cache->key.objectid, cache->key.offset,
+                       btrfs_block_group_used(&cache->item), cache->pinned,
+                       cache->reserved, cache->ro ? "[readonly]" : "");
                btrfs_dump_free_space(cache, bytes);
                spin_unlock(&cache->lock);
        }
@@ -7949,6 +7949,7 @@ int btrfs_reserve_extent(struct btrfs_root *root, u64 ram_bytes,
                         u64 empty_size, u64 hint_byte,
                         struct btrfs_key *ins, int is_data, int delalloc)
 {
+       struct btrfs_fs_info *fs_info = root->fs_info;
        bool final_tried = num_bytes == min_alloc_size;
        u64 flags;
        int ret;
@@ -7959,8 +7960,7 @@ again:
        ret = find_free_extent(root, ram_bytes, num_bytes, empty_size,
                               hint_byte, ins, flags, delalloc);
        if (!ret && !is_data) {
-               btrfs_dec_block_group_reservations(root->fs_info,
-                                                  ins->objectid);
+               btrfs_dec_block_group_reservations(fs_info, ins->objectid);
        } else if (ret == -ENOSPC) {
                if (!final_tried && ins->offset) {
                        num_bytes = min(num_bytes >> 1, ins->offset);
@@ -7970,14 +7970,15 @@ again:
                        if (num_bytes == min_alloc_size)
                                final_tried = true;
                        goto again;
-               } else if (btrfs_test_opt(root->fs_info, ENOSPC_DEBUG)) {
+               } else if (btrfs_test_opt(fs_info, ENOSPC_DEBUG)) {
                        struct btrfs_space_info *sinfo;
 
-                       sinfo = __find_space_info(root->fs_info, flags);
-                       btrfs_err(root->fs_info, "allocation failed flags %llu, wanted %llu",
-                               flags, num_bytes);
+                       sinfo = __find_space_info(fs_info, flags);
+                       btrfs_err(root->fs_info,
+                                 "allocation failed flags %llu, wanted %llu",
+                                 flags, num_bytes);
                        if (sinfo)
-                               dump_space_info(sinfo, num_bytes, 1);
+                               dump_space_info(fs_info, sinfo, num_bytes, 1);
                }
        }
 
@@ -8465,7 +8466,6 @@ static noinline void reada_walk_down(struct btrfs_trans_handle *trans,
        u64 refs;
        u64 flags;
        u32 nritems;
-       u32 blocksize;
        struct btrfs_key key;
        struct extent_buffer *eb;
        int ret;
@@ -8483,7 +8483,6 @@ static noinline void reada_walk_down(struct btrfs_trans_handle *trans,
 
        eb = path->nodes[wc->level];
        nritems = btrfs_header_nritems(eb);
-       blocksize = root->nodesize;
 
        for (slot = path->slots[wc->level]; slot < nritems; slot++) {
                if (nread >= wc->reada_count)
@@ -8547,7 +8546,7 @@ static int account_leaf_items(struct btrfs_trans_handle *trans,
        u64 bytenr, num_bytes;
 
        /* We can be called directly from walk_up_proc() */
-       if (!root->fs_info->quota_enabled)
+       if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags))
                return 0;
 
        for (i = 0; i < nr; i++) {
@@ -8656,7 +8655,7 @@ static int account_shared_subtree(struct btrfs_trans_handle *trans,
        BUG_ON(root_level < 0 || root_level > BTRFS_MAX_LEVEL);
        BUG_ON(root_eb == NULL);
 
-       if (!root->fs_info->quota_enabled)
+       if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &root->fs_info->flags))
                return 0;
 
        if (!extent_buffer_uptodate(root_eb)) {
@@ -8887,14 +8886,13 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
        ret = btrfs_lookup_extent_info(trans, root, bytenr, level - 1, 1,
                                       &wc->refs[level - 1],
                                       &wc->flags[level - 1]);
-       if (ret < 0) {
-               btrfs_tree_unlock(next);
-               return ret;
-       }
+       if (ret < 0)
+               goto out_unlock;
 
        if (unlikely(wc->refs[level - 1] == 0)) {
                btrfs_err(root->fs_info, "Missing references.");
-               BUG();
+               ret = -EIO;
+               goto out_unlock;
        }
        *lookup_info = 0;
 
@@ -8946,7 +8944,12 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
        }
 
        level--;
-       BUG_ON(level != btrfs_header_level(next));
+       ASSERT(level == btrfs_header_level(next));
+       if (level != btrfs_header_level(next)) {
+               btrfs_err(root->fs_info, "mismatched level");
+               ret = -EIO;
+               goto out_unlock;
+       }
        path->nodes[level] = next;
        path->slots[level] = 0;
        path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING;
@@ -8961,8 +8964,15 @@ skip:
                if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF) {
                        parent = path->nodes[level]->start;
                } else {
-                       BUG_ON(root->root_key.objectid !=
+                       ASSERT(root->root_key.objectid ==
                               btrfs_header_owner(path->nodes[level]));
+                       if (root->root_key.objectid !=
+                           btrfs_header_owner(path->nodes[level])) {
+                               btrfs_err(root->fs_info,
+                                               "mismatched block owner");
+                               ret = -EIO;
+                               goto out_unlock;
+                       }
                        parent = 0;
                }
 
@@ -8971,20 +8981,24 @@ skip:
                                                     generation, level - 1);
                        if (ret) {
                                btrfs_err_rl(root->fs_info,
-                                       "Error "
-                                       "%d accounting shared subtree. Quota "
-                                       "is out of sync, rescan required.",
-                                       ret);
+                                            "Error %d accounting shared subtree. Quota is out of sync, rescan required.",
+                                            ret);
                        }
                }
                ret = btrfs_free_extent(trans, root, bytenr, blocksize, parent,
                                root->root_key.objectid, level - 1, 0);
-               BUG_ON(ret); /* -ENOMEM */
+               if (ret)
+                       goto out_unlock;
        }
+
+       *lookup_info = 1;
+       ret = 1;
+
+out_unlock:
        btrfs_tree_unlock(next);
        free_extent_buffer(next);
-       *lookup_info = 1;
-       return 1;
+
+       return ret;
 }
 
 /*
@@ -9064,10 +9078,8 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
                        ret = account_leaf_items(trans, root, eb);
                        if (ret) {
                                btrfs_err_rl(root->fs_info,
-                                       "error "
-                                       "%d accounting leaf items. Quota "
-                                       "is out of sync, rescan required.",
-                                       ret);
+                                            "error %d accounting leaf items. Quota is out of sync, rescan required.",
+                                            ret);
                        }
                }
                /* make block locked assertion in clean_tree_block happy */
@@ -9183,9 +9195,10 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
                         struct btrfs_block_rsv *block_rsv, int update_ref,
                         int for_reloc)
 {
+       struct btrfs_fs_info *fs_info = root->fs_info;
        struct btrfs_path *path;
        struct btrfs_trans_handle *trans;
-       struct btrfs_root *tree_root = root->fs_info->tree_root;
+       struct btrfs_root *tree_root = fs_info->tree_root;
        struct btrfs_root_item *root_item = &root->root_item;
        struct walk_control *wc;
        struct btrfs_key key;
@@ -9194,7 +9207,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
        int level;
        bool root_dropped = false;
 
-       btrfs_debug(root->fs_info, "Drop subvolume %llu", root->objectid);
+       btrfs_debug(fs_info, "Drop subvolume %llu", root->objectid);
 
        path = btrfs_alloc_path();
        if (!path) {
@@ -9323,7 +9336,8 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
 
                        btrfs_end_transaction_throttle(trans, tree_root);
                        if (!for_reloc && btrfs_need_cleaner_sleep(root)) {
-                               pr_debug("BTRFS: drop snapshot early exit\n");
+                               btrfs_debug(fs_info,
+                                           "drop snapshot early exit");
                                err = -EAGAIN;
                                goto out_free;
                        }
@@ -9389,7 +9403,7 @@ out:
        if (!for_reloc && root_dropped == false)
                btrfs_add_dead_root(root);
        if (err && err != -EAGAIN)
-               btrfs_handle_fs_error(root->fs_info, err, NULL);
+               btrfs_handle_fs_error(fs_info, err, NULL);
        return err;
 }
 
@@ -10023,7 +10037,7 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
                if (WARN_ON(space_info->bytes_pinned > 0 ||
                            space_info->bytes_reserved > 0 ||
                            space_info->bytes_may_use > 0))
-                       dump_space_info(space_info, 0, 0);
+                       dump_space_info(info, space_info, 0, 0);
                list_del(&space_info->list);
                for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) {
                        struct kobject *kobj;
@@ -10072,7 +10086,8 @@ static void __link_block_group(struct btrfs_space_info *space_info,
 
        return;
 out_err:
-       pr_warn("BTRFS: failed to add kobject for block cache. ignoring.\n");
+       btrfs_warn(cache->fs_info,
+                  "failed to add kobject for block cache, ignoring");
 }
 
 static struct btrfs_block_group_cache *
@@ -10130,6 +10145,11 @@ int btrfs_read_block_groups(struct btrfs_root *root)
        struct extent_buffer *leaf;
        int need_clear = 0;
        u64 cache_gen;
+       u64 feature;
+       int mixed;
+
+       feature = btrfs_super_incompat_flags(info->super_copy);
+       mixed = !!(feature & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS);
 
        root = info->extent_root;
        key.objectid = 0;
@@ -10183,6 +10203,15 @@ int btrfs_read_block_groups(struct btrfs_root *root)
                                   btrfs_item_ptr_offset(leaf, path->slots[0]),
                                   sizeof(cache->item));
                cache->flags = btrfs_block_group_flags(&cache->item);
+               if (!mixed &&
+                   ((cache->flags & BTRFS_BLOCK_GROUP_METADATA) &&
+                   (cache->flags & BTRFS_BLOCK_GROUP_DATA))) {
+                       btrfs_err(info,
+"bg %llu is a mixed block group but filesystem hasn't enabled mixed block groups",
+                                 cache->key.objectid);
+                       ret = -EINVAL;
+                       goto error;
+               }
 
                key.objectid = found_key.objectid + found_key.offset;
                btrfs_release_path(path);
@@ -10792,7 +10821,7 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
        struct btrfs_trans_handle *trans;
        int ret = 0;
 
-       if (!fs_info->open)
+       if (!test_bit(BTRFS_FS_OPEN, &fs_info->flags))
                return;
 
        spin_lock(&fs_info->unused_bgs_lock);