Btrfs: Fixup last found extent caching
authorChris Mason <chris.mason@oracle.com>
Wed, 7 Mar 2007 21:15:30 +0000 (16:15 -0500)
committerDavid Woodhouse <dwmw2@hera.kernel.org>
Wed, 7 Mar 2007 21:15:30 +0000 (16:15 -0500)
Signed-off-by: Chris Mason <chris.mason@oracle.com>
fs/btrfs/Makefile
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c

index d92d08dde0ffb1d0f76b30667ea5998acbe90235..ae7f4c00c39cd6a87a0ef88534b487b904bca609 100644 (file)
@@ -1,6 +1,6 @@
 
 CC=gcc
-CFLAGS = -Wall
+CFLAGS = -g -Wall
 headers = radix-tree.h ctree.h disk-io.h kerncompat.h print-tree.h list.h
 objects = ctree.o disk-io.o radix-tree.o mkfs.o extent-tree.o print-tree.o
 
index 4a7bc4e6e7471a5e6e87a613b96d2096f71e7d5f..518326fa36948c17552bc3ae20fbb74cac127230 100644 (file)
@@ -54,6 +54,7 @@ struct ctree_root {
        struct tree_buffer *commit_root;
        struct ctree_root *extent_root;
        struct key current_insert;
+       struct key last_insert;
        int fp;
        struct radix_tree_root cache_radix;
        struct radix_tree_root pinned_radix;
index 2fe31c3508c147c268fff8ed7d4c9ec3eeb1be75..997cc578a1852f7ee4379394c61955b16a2b0917 100644 (file)
@@ -186,6 +186,7 @@ static int __setup_root(struct ctree_root *root, struct ctree_root *extent_root,
        root->commit_root = NULL;
        root->node = read_tree_block(root, info->tree_root);
        memset(&root->current_insert, 0, sizeof(root->current_insert));
+       memset(&root->last_insert, 0, sizeof(root->last_insert));
        return 0;
 }
 
index 8a2b8aaf9b868e5fc3d5bc4dcd52d9085a839ded..dd11532cb2f645085710d1f7cf3f3a84f3d34941 100644 (file)
@@ -102,9 +102,12 @@ int btrfs_finish_extent_commit(struct ctree_root *root)
                                                 ARRAY_SIZE(gang));
                if (!ret)
                        break;
-               for (i = 0; i < ret; i++)
+               for (i = 0; i < ret; i++) {
                        radix_tree_delete(&extent_root->pinned_radix, gang[i]);
+               }
        }
+       extent_root->last_insert.objectid = 0;
+       extent_root->last_insert.offset = 0;
        return 0;
 }
 
@@ -170,6 +173,9 @@ int __free_extent(struct ctree_root *root, u64 blocknr, u64 num_blocks)
                        radix_tree_preload_end();
                }
                ret = del_item(extent_root, &path);
+               if (root != extent_root &&
+                   extent_root->last_insert.objectid < blocknr)
+                       extent_root->last_insert.objectid = blocknr;
                if (ret)
                        BUG();
        }
@@ -261,8 +267,11 @@ static int find_free_extent(struct ctree_root *orig_root, u64 num_blocks,
        int start_found;
        struct leaf *l;
        struct ctree_root * root = orig_root->extent_root;
-       int total_needed = num_blocks + MAX_LEVEL * 3;
+       int total_needed = num_blocks;
 
+       total_needed += (node_level(root->node->node.header.flags) + 1) * 3;
+       if (root->last_insert.objectid > search_start)
+               search_start = root->last_insert.objectid;
 check_failed:
        init_path(&path);
        ins->objectid = search_start;
@@ -273,6 +282,9 @@ check_failed:
        if (ret < 0)
                goto error;
 
+       if (path.slots[0] > 0)
+               path.slots[0]--;
+
        while (1) {
                l = &path.nodes[0]->leaf;
                slot = path.slots[0];
@@ -293,31 +305,21 @@ check_failed:
                        ins->offset = (u64)-1;
                        goto check_pending;
                }
-               if (slot == 0) {
-                       int last_slot = l->header.nritems - 1;
-                       u64 span = l->items[last_slot].key.objectid;
-                       span -= l->items[slot].key.objectid;
-                       if (span + total_needed > last_slot - slot) {
-                               path.slots[0] = last_slot + 1;
-                               key = &l->items[last_slot].key;
-                               last_block = key->objectid + key->offset;
-                               start_found = 1;
-                               continue;
-                       }
-               }
                key = &l->items[slot].key;
                if (key->objectid >= search_start) {
                        if (start_found) {
+                               if (last_block < search_start)
+                                       last_block = search_start;
                                hole_size = key->objectid - last_block;
                                if (hole_size > total_needed) {
                                        ins->objectid = last_block;
                                        ins->offset = hole_size;
                                        goto check_pending;
                                }
-                       } else
-                               start_found = 1;
-                       last_block = key->objectid + key->offset;
+                       }
                }
+               start_found = 1;
+               last_block = key->objectid + key->offset;
                path.slots[0]++;
        }
        // FIXME -ENOSPC
@@ -335,9 +337,10 @@ check_pending:
                }
        }
        BUG_ON(root->current_insert.offset);
-       root->current_insert.offset = total_needed;
+       root->current_insert.offset = total_needed - num_blocks;
        root->current_insert.objectid = ins->objectid + num_blocks;
        root->current_insert.flags = 0;
+       root->last_insert.objectid = ins->objectid;
        ins->offset = num_blocks;
        return 0;
 error: