Btrfs: use a separate flag for search_start vs a hint in find_free_extent
authorChris Mason <chris.mason@oracle.com>
Wed, 30 May 2007 14:22:12 +0000 (10:22 -0400)
committerDavid Woodhouse <dwmw2@hera.kernel.org>
Wed, 30 May 2007 14:22:12 +0000 (10:22 -0400)
Signed-off-by: Chris Mason <chris.mason@oracle.com>
fs/btrfs/extent-tree.c

index b6dc020bdde9e83c08d78d68a6f0803c9f8a0cdb..85616b458e18cb5e39f653a14cea3e9c81000305 100644 (file)
@@ -5,8 +5,9 @@
 #include "transaction.h"
 
 static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
-                           *orig_root, u64 num_blocks, u64 search_start, u64
-                           search_end, struct btrfs_key *ins, int data);
+                           *orig_root, u64 num_blocks, u64 search_start,
+                           u64 search_end, u64 hint_block,
+                           struct btrfs_key *ins, int data);
 static int finish_current_insert(struct btrfs_trans_handle *trans, struct
                                 btrfs_root *extent_root);
 static int del_pending_extents(struct btrfs_trans_handle *trans, struct
@@ -157,12 +158,6 @@ static struct btrfs_block_group_cache *lookup_block_group(struct
                    block_group->key.objectid + block_group->key.offset)
                        return block_group;
        }
-       WARN_ON(1);
-       printk("lookup_block_group fails for blocknr %Lu\n", blocknr);
-       printk("last ret was %d\n", ret);
-       if (ret) {
-               printk("last block group was %Lu %Lu\n", block_group->key.objectid, block_group->key.offset);
-       }
        return NULL;
 }
 
@@ -378,7 +373,7 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
        struct btrfs_key ins;
        u32 refs;
 
-       find_free_extent(trans, root->fs_info->extent_root, 0, 0, (u64)-1,
+       find_free_extent(trans, root->fs_info->extent_root, 0, 0, (u64)-1, 0,
                         &ins, 0);
        path = btrfs_alloc_path();
        BUG_ON(!path);
@@ -495,7 +490,7 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans,
        struct btrfs_block_group_item *bi;
        struct btrfs_key ins;
 
-       find_free_extent(trans, extent_root, 0, 0, (u64)-1, &ins, 0);
+       find_free_extent(trans, extent_root, 0, 0, (u64)-1, 0, &ins, 0);
        ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1);
        BUG_ON(ret);
        bi = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0],
@@ -788,7 +783,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
        btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
        key.offset = num_blocks;
 
-       find_free_extent(trans, root, 0, 0, (u64)-1, &ins, 0);
+       find_free_extent(trans, root, 0, 0, (u64)-1, 0, &ins, 0);
        path = btrfs_alloc_path();
        BUG_ON(!path);
        btrfs_init_path(path);
@@ -906,7 +901,8 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
  */
 static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
                            *orig_root, u64 num_blocks, u64 search_start, u64
-                           search_end, struct btrfs_key *ins, int data)
+                           search_end, u64 hint_block,
+                           struct btrfs_key *ins, int data)
 {
        struct btrfs_path *path;
        struct btrfs_key key;
@@ -926,6 +922,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
        int level;
        struct btrfs_block_group_cache *block_group;
        int full_scan = 0;
+       int wrapped = 0;
        u64 limit;
 
        path = btrfs_alloc_path();
@@ -940,10 +937,10 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
        }
        if (search_end == (u64)-1)
                search_end = btrfs_super_total_blocks(info->disk_super);
-       if (search_start) {
-               block_group = lookup_block_group(info, search_start);
+       if (hint_block) {
+               block_group = lookup_block_group(info, hint_block);
                block_group = btrfs_find_block_group(root, block_group,
-                                                    search_start, data, 1);
+                                                    hint_block, data, 1);
        } else {
                block_group = btrfs_find_block_group(root,
                                                     trans->block_group, 0,
@@ -954,7 +951,7 @@ check_failed:
        if (!block_group->data)
                search_start = find_search_start(root, &block_group,
                                                 search_start, total_needed);
-       else
+       else if (!full_scan)
                search_start = max(block_group->last_alloc, search_start);
 
        btrfs_init_path(path);
@@ -1039,7 +1036,7 @@ check_failed:
 
                start_found = 1;
                last_block = key.objectid + key.offset;
-               if (last_block >= block_group->key.objectid +
+               if (!full_scan && last_block >= block_group->key.objectid +
                    block_group->key.offset) {
                        btrfs_release_path(root, path);
                        search_start = block_group->key.objectid +
@@ -1059,10 +1056,15 @@ check_pending:
        BUG_ON(ins->objectid < search_start);
 
        if (ins->objectid + num_blocks >= search_end) {
-               if (full_scan)
-                       return -ENOSPC;
+               if (full_scan) {
+                       ret = -ENOSPC;
+                       goto error;
+               }
                search_start = orig_search_start;
-               full_scan = 1;
+               if (wrapped)
+                       full_scan = 1;
+               else
+                       wrapped = 1;
                goto new_group;
        }
        for (test_block = ins->objectid;
@@ -1132,14 +1134,20 @@ check_pending:
 new_group:
        if (search_start + num_blocks >= search_end) {
                search_start = orig_search_start;
-printk("doing full scan!\n");
-               full_scan = 1;
+               if (full_scan) {
+                       ret = -ENOSPC;
+                       goto error;
+               }
+               if (wrapped)
+                       full_scan = 1;
+               else
+                       wrapped = 1;
        }
        block_group = lookup_block_group(info, search_start);
+       cond_resched();
        if (!full_scan)
                block_group = btrfs_find_block_group(root, block_group,
                                                     search_start, data, 0);
-       cond_resched();
        goto check_failed;
 
 error:
@@ -1156,12 +1164,13 @@ error:
  */
 int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
                       struct btrfs_root *root, u64 owner,
-                      u64 num_blocks, u64 search_start,
+                      u64 num_blocks, u64 hint_block,
                       u64 search_end, struct btrfs_key *ins, int data)
 {
        int ret;
        int pending_ret;
        u64 super_blocks_used;
+       u64 search_start = 0;
        struct btrfs_fs_info *info = root->fs_info;
        struct btrfs_root *extent_root = info->extent_root;
        struct btrfs_extent_item extent_item;
@@ -1193,7 +1202,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
         */
        if (data) {
                ret = find_free_extent(trans, root, 0, 0,
-                                      search_end, &prealloc_key, 0);
+                                      search_end, 0, &prealloc_key, 0);
                if (ret) {
                        return ret;
                }
@@ -1204,9 +1213,11 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
                        search_start = info->extent_tree_prealloc[0] + 1;
                }
        }
+       if (hint_block < search_start)
+               hint_block = search_start;
        /* do the real allocation */
        ret = find_free_extent(trans, root, num_blocks, search_start,
-                              search_end, ins, data);
+                              search_end, hint_block, ins, data);
        if (ret) {
                return ret;
        }
@@ -1226,8 +1237,12 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
                else
                        search_start = ins->objectid + ins->offset;
 
+               if (hint_block < search_start)
+                       hint_block = search_start;
+
                ret = find_free_extent(trans, root, 0, search_start,
-                                      search_end, &prealloc_key, 0);
+                                      search_end, hint_block,
+                                      &prealloc_key, 0);
                if (ret) {
                        return ret;
                }