Btrfs: fix data corruption after fast fsync and writeback error
[deliverable/linux.git] / fs / btrfs / extent-tree.c
index 3efe1c3877bf34c4643ce99fb90d52fedda74d06..b30ddb49cfab2dc62d7b6c16c3b9ea892b5d33c6 100644 (file)
@@ -491,7 +491,7 @@ next:
                                                          key.objectid);
                        if (key.type == BTRFS_METADATA_ITEM_KEY)
                                last = key.objectid +
-                                       fs_info->tree_root->leafsize;
+                                       fs_info->tree_root->nodesize;
                        else
                                last = key.objectid + key.offset;
 
@@ -765,7 +765,7 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
         * different
         */
        if (metadata && !btrfs_fs_incompat(root->fs_info, SKINNY_METADATA)) {
-               offset = root->leafsize;
+               offset = root->nodesize;
                metadata = 0;
        }
 
@@ -799,13 +799,13 @@ again:
                                              path->slots[0]);
                        if (key.objectid == bytenr &&
                            key.type == BTRFS_EXTENT_ITEM_KEY &&
-                           key.offset == root->leafsize)
+                           key.offset == root->nodesize)
                                ret = 0;
                }
                if (ret) {
                        key.objectid = bytenr;
                        key.type = BTRFS_EXTENT_ITEM_KEY;
-                       key.offset = root->leafsize;
+                       key.offset = root->nodesize;
                        btrfs_release_path(path);
                        goto again;
                }
@@ -2651,7 +2651,7 @@ int btrfs_check_space_for_delayed_refs(struct btrfs_trans_handle *trans,
        num_bytes = btrfs_calc_trans_metadata_size(root, 1);
        num_heads = heads_to_leaves(root, num_heads);
        if (num_heads > 1)
-               num_bytes += (num_heads - 1) * root->leafsize;
+               num_bytes += (num_heads - 1) * root->nodesize;
        num_bytes <<= 1;
        global_rsv = &root->fs_info->global_block_rsv;
 
@@ -3097,7 +3097,7 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans,
        for (i = 0; i < nritems; i++) {
                if (level == 0) {
                        btrfs_item_key_to_cpu(buf, &key, i);
-                       if (btrfs_key_type(&key) != BTRFS_EXTENT_DATA_KEY)
+                       if (key.type != BTRFS_EXTENT_DATA_KEY)
                                continue;
                        fi = btrfs_item_ptr(buf, i,
                                            struct btrfs_file_extent_item);
@@ -3117,7 +3117,7 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans,
                                goto fail;
                } else {
                        bytenr = btrfs_node_blockptr(buf, i);
-                       num_bytes = btrfs_level_size(root, level - 1);
+                       num_bytes = root->nodesize;
                        ret = process_func(trans, root, bytenr, num_bytes,
                                           parent, ref_root, level - 1, 0,
                                           1);
@@ -4343,11 +4343,21 @@ static inline int need_do_async_reclaim(struct btrfs_space_info *space_info,
 }
 
 static int btrfs_need_do_async_reclaim(struct btrfs_space_info *space_info,
-                                      struct btrfs_fs_info *fs_info)
+                                      struct btrfs_fs_info *fs_info,
+                                      int flush_state)
 {
        u64 used;
 
        spin_lock(&space_info->lock);
+       /*
+        * We run out of space and have not got any free space via flush_space,
+        * so don't bother doing async reclaim.
+        */
+       if (flush_state > COMMIT_TRANS && space_info->full) {
+               spin_unlock(&space_info->lock);
+               return 0;
+       }
+
        used = space_info->bytes_used + space_info->bytes_reserved +
               space_info->bytes_pinned + space_info->bytes_readonly +
               space_info->bytes_may_use;
@@ -4380,11 +4390,12 @@ static void btrfs_async_reclaim_metadata_space(struct work_struct *work)
                flush_space(fs_info->fs_root, space_info, to_reclaim,
                            to_reclaim, flush_state);
                flush_state++;
-               if (!btrfs_need_do_async_reclaim(space_info, fs_info))
+               if (!btrfs_need_do_async_reclaim(space_info, fs_info,
+                                                flush_state))
                        return;
        } while (flush_state <= COMMIT_TRANS);
 
-       if (btrfs_need_do_async_reclaim(space_info, fs_info))
+       if (btrfs_need_do_async_reclaim(space_info, fs_info, flush_state))
                queue_work(system_unbound_wq, work);
 }
 
@@ -4839,7 +4850,7 @@ static u64 calc_global_metadata_size(struct btrfs_fs_info *fs_info)
        if (num_bytes * 3 > meta_used)
                num_bytes = div64_u64(meta_used, 3);
 
-       return ALIGN(num_bytes, fs_info->extent_root->leafsize << 10);
+       return ALIGN(num_bytes, fs_info->extent_root->nodesize << 10);
 }
 
 static void update_global_block_rsv(struct btrfs_fs_info *fs_info)
@@ -4988,7 +4999,7 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
 
        if (root->fs_info->quota_enabled) {
                /* One for parent inode, two for dir entries */
-               num_bytes = 3 * root->leafsize;
+               num_bytes = 3 * root->nodesize;
                ret = btrfs_qgroup_reserve(root, num_bytes);
                if (ret)
                        return ret;
@@ -5176,7 +5187,7 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
 
        if (root->fs_info->quota_enabled) {
                ret = btrfs_qgroup_reserve(root, num_bytes +
-                                          nr_extents * root->leafsize);
+                                          nr_extents * root->nodesize);
                if (ret)
                        goto out_fail;
        }
@@ -5185,7 +5196,7 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
        if (unlikely(ret)) {
                if (root->fs_info->quota_enabled)
                        btrfs_qgroup_free(root, num_bytes +
-                                               nr_extents * root->leafsize);
+                                               nr_extents * root->nodesize);
                goto out_fail;
        }
 
@@ -5301,7 +5312,7 @@ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes)
                                      btrfs_ino(inode), to_free, 0);
        if (root->fs_info->quota_enabled) {
                btrfs_qgroup_free(root, num_bytes +
-                                       dropped * root->leafsize);
+                                       dropped * root->nodesize);
        }
 
        btrfs_block_rsv_release(root, &root->fs_info->delalloc_block_rsv,
@@ -6263,14 +6274,6 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root,
        return ret;
 }
 
-static u64 stripe_align(struct btrfs_root *root,
-                       struct btrfs_block_group_cache *cache,
-                       u64 val, u64 num_bytes)
-{
-       u64 ret = ALIGN(val, root->stripesize);
-       return ret;
-}
-
 /*
  * when we wait for progress in the block group caching, its because
  * our allocation attempt failed at least once.  So, we must sleep
@@ -6464,7 +6467,7 @@ static noinline int find_free_extent(struct btrfs_root *orig_root,
        bool have_caching_bg = false;
 
        WARN_ON(num_bytes < root->sectorsize);
-       btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY);
+       ins->type = BTRFS_EXTENT_ITEM_KEY;
        ins->objectid = 0;
        ins->offset = 0;
 
@@ -6751,8 +6754,7 @@ unclustered_alloc:
                        goto loop;
                }
 checks:
-               search_start = stripe_align(root, block_group,
-                                           offset, num_bytes);
+               search_start = ALIGN(offset, root->stripesize);
 
                /* move on to the next group */
                if (search_start + num_bytes >
@@ -7077,7 +7079,7 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
        path = btrfs_alloc_path();
        if (!path) {
                btrfs_free_and_pin_reserved_extent(root, ins->objectid,
-                                                  root->leafsize);
+                                                  root->nodesize);
                return -ENOMEM;
        }
 
@@ -7086,7 +7088,7 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
                                      ins, size);
        if (ret) {
                btrfs_free_and_pin_reserved_extent(root, ins->objectid,
-                                                  root->leafsize);
+                                                  root->nodesize);
                btrfs_free_path(path);
                return ret;
        }
@@ -7101,7 +7103,7 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
 
        if (skinny_metadata) {
                iref = (struct btrfs_extent_inline_ref *)(extent_item + 1);
-               num_bytes = root->leafsize;
+               num_bytes = root->nodesize;
        } else {
                block_info = (struct btrfs_tree_block_info *)(extent_item + 1);
                btrfs_set_tree_block_key(leaf, block_info, key);
@@ -7131,14 +7133,14 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
                        return ret;
        }
 
-       ret = update_block_group(root, ins->objectid, root->leafsize, 1);
+       ret = update_block_group(root, ins->objectid, root->nodesize, 1);
        if (ret) { /* -ENOENT, logic error */
                btrfs_err(fs_info, "update block group failed for %llu %llu",
                        ins->objectid, ins->offset);
                BUG();
        }
 
-       trace_btrfs_reserved_extent_alloc(root, ins->objectid, root->leafsize);
+       trace_btrfs_reserved_extent_alloc(root, ins->objectid, root->nodesize);
        return ret;
 }
 
@@ -7417,7 +7419,7 @@ static noinline void reada_walk_down(struct btrfs_trans_handle *trans,
 
        eb = path->nodes[wc->level];
        nritems = btrfs_header_nritems(eb);
-       blocksize = btrfs_level_size(root, wc->level - 1);
+       blocksize = root->nodesize;
 
        for (slot = path->slots[wc->level]; slot < nritems; slot++) {
                if (nread >= wc->reada_count)
@@ -7806,7 +7808,7 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
        }
 
        bytenr = btrfs_node_blockptr(path->nodes[level], path->slots[level]);
-       blocksize = btrfs_level_size(root, level - 1);
+       blocksize = root->nodesize;
 
        next = btrfs_find_tree_block(root, bytenr, blocksize);
        if (!next) {
@@ -9009,7 +9011,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
        root = info->extent_root;
        key.objectid = 0;
        key.offset = 0;
-       btrfs_set_key_type(&key, BTRFS_BLOCK_GROUP_ITEM_KEY);
+       key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
@@ -9413,8 +9415,6 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
 
        memcpy(&key, &block_group->key, sizeof(key));
 
-       btrfs_clear_space_info_full(root->fs_info);
-
        btrfs_put_block_group(block_group);
        btrfs_put_block_group(block_group);
 
This page took 0.032529 seconds and 5 git commands to generate.