diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-03-07 16:15:30 -0500 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-03-07 16:15:30 -0500 |
commit | 0579da4280812f34f382fb0f8004d7b0219e7a33 (patch) | |
tree | 817da9340020ac01849b610b90f6803d81bc97d3 /fs/btrfs/extent-tree.c | |
parent | 037e6390488af8ab96137e1e5cccc15ad14ef887 (diff) |
Btrfs: Fixup last found extent caching
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 39 |
1 files changed, 21 insertions, 18 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 8a2b8aaf9b86..dd11532cb2f6 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -102,9 +102,12 @@ int btrfs_finish_extent_commit(struct ctree_root *root) | |||
102 | ARRAY_SIZE(gang)); | 102 | ARRAY_SIZE(gang)); |
103 | if (!ret) | 103 | if (!ret) |
104 | break; | 104 | break; |
105 | for (i = 0; i < ret; i++) | 105 | for (i = 0; i < ret; i++) { |
106 | radix_tree_delete(&extent_root->pinned_radix, gang[i]); | 106 | radix_tree_delete(&extent_root->pinned_radix, gang[i]); |
107 | } | ||
107 | } | 108 | } |
109 | extent_root->last_insert.objectid = 0; | ||
110 | extent_root->last_insert.offset = 0; | ||
108 | return 0; | 111 | return 0; |
109 | } | 112 | } |
110 | 113 | ||
@@ -170,6 +173,9 @@ int __free_extent(struct ctree_root *root, u64 blocknr, u64 num_blocks) | |||
170 | radix_tree_preload_end(); | 173 | radix_tree_preload_end(); |
171 | } | 174 | } |
172 | ret = del_item(extent_root, &path); | 175 | ret = del_item(extent_root, &path); |
176 | if (root != extent_root && | ||
177 | extent_root->last_insert.objectid < blocknr) | ||
178 | extent_root->last_insert.objectid = blocknr; | ||
173 | if (ret) | 179 | if (ret) |
174 | BUG(); | 180 | BUG(); |
175 | } | 181 | } |
@@ -261,8 +267,11 @@ static int find_free_extent(struct ctree_root *orig_root, u64 num_blocks, | |||
261 | int start_found; | 267 | int start_found; |
262 | struct leaf *l; | 268 | struct leaf *l; |
263 | struct ctree_root * root = orig_root->extent_root; | 269 | struct ctree_root * root = orig_root->extent_root; |
264 | int total_needed = num_blocks + MAX_LEVEL * 3; | 270 | int total_needed = num_blocks; |
265 | 271 | ||
272 | total_needed += (node_level(root->node->node.header.flags) + 1) * 3; | ||
273 | if (root->last_insert.objectid > search_start) | ||
274 | search_start = root->last_insert.objectid; | ||
266 | check_failed: | 275 | check_failed: |
267 | init_path(&path); | 276 | init_path(&path); |
268 | ins->objectid = search_start; | 277 | ins->objectid = search_start; |
@@ -273,6 +282,9 @@ check_failed: | |||
273 | if (ret < 0) | 282 | if (ret < 0) |
274 | goto error; | 283 | goto error; |
275 | 284 | ||
285 | if (path.slots[0] > 0) | ||
286 | path.slots[0]--; | ||
287 | |||
276 | while (1) { | 288 | while (1) { |
277 | l = &path.nodes[0]->leaf; | 289 | l = &path.nodes[0]->leaf; |
278 | slot = path.slots[0]; | 290 | slot = path.slots[0]; |
@@ -293,31 +305,21 @@ check_failed: | |||
293 | ins->offset = (u64)-1; | 305 | ins->offset = (u64)-1; |
294 | goto check_pending; | 306 | goto check_pending; |
295 | } | 307 | } |
296 | if (slot == 0) { | ||
297 | int last_slot = l->header.nritems - 1; | ||
298 | u64 span = l->items[last_slot].key.objectid; | ||
299 | span -= l->items[slot].key.objectid; | ||
300 | if (span + total_needed > last_slot - slot) { | ||
301 | path.slots[0] = last_slot + 1; | ||
302 | key = &l->items[last_slot].key; | ||
303 | last_block = key->objectid + key->offset; | ||
304 | start_found = 1; | ||
305 | continue; | ||
306 | } | ||
307 | } | ||
308 | key = &l->items[slot].key; | 308 | key = &l->items[slot].key; |
309 | if (key->objectid >= search_start) { | 309 | if (key->objectid >= search_start) { |
310 | if (start_found) { | 310 | if (start_found) { |
311 | if (last_block < search_start) | ||
312 | last_block = search_start; | ||
311 | hole_size = key->objectid - last_block; | 313 | hole_size = key->objectid - last_block; |
312 | if (hole_size > total_needed) { | 314 | if (hole_size > total_needed) { |
313 | ins->objectid = last_block; | 315 | ins->objectid = last_block; |
314 | ins->offset = hole_size; | 316 | ins->offset = hole_size; |
315 | goto check_pending; | 317 | goto check_pending; |
316 | } | 318 | } |
317 | } else | 319 | } |
318 | start_found = 1; | ||
319 | last_block = key->objectid + key->offset; | ||
320 | } | 320 | } |
321 | start_found = 1; | ||
322 | last_block = key->objectid + key->offset; | ||
321 | path.slots[0]++; | 323 | path.slots[0]++; |
322 | } | 324 | } |
323 | // FIXME -ENOSPC | 325 | // FIXME -ENOSPC |
@@ -335,9 +337,10 @@ check_pending: | |||
335 | } | 337 | } |
336 | } | 338 | } |
337 | BUG_ON(root->current_insert.offset); | 339 | BUG_ON(root->current_insert.offset); |
338 | root->current_insert.offset = total_needed; | 340 | root->current_insert.offset = total_needed - num_blocks; |
339 | root->current_insert.objectid = ins->objectid + num_blocks; | 341 | root->current_insert.objectid = ins->objectid + num_blocks; |
340 | root->current_insert.flags = 0; | 342 | root->current_insert.flags = 0; |
343 | root->last_insert.objectid = ins->objectid; | ||
341 | ins->offset = num_blocks; | 344 | ins->offset = num_blocks; |
342 | return 0; | 345 | return 0; |
343 | error: | 346 | error: |