aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.h10
-rw-r--r--fs/btrfs/disk-io.c3
-rw-r--r--fs/btrfs/extent-tree.c101
3 files changed, 87 insertions, 27 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 2d166ca8b104..26d0cdd46f49 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -244,12 +244,17 @@ struct btrfs_fs_info {
244 struct btrfs_root *extent_root; 244 struct btrfs_root *extent_root;
245 struct btrfs_root *tree_root; 245 struct btrfs_root *tree_root;
246 struct btrfs_root *dev_root; 246 struct btrfs_root *dev_root;
247 struct btrfs_key current_insert;
248 struct btrfs_key last_insert; 247 struct btrfs_key last_insert;
249 struct radix_tree_root fs_roots_radix; 248 struct radix_tree_root fs_roots_radix;
250 struct radix_tree_root pending_del_radix; 249 struct radix_tree_root pending_del_radix;
251 struct radix_tree_root pinned_radix; 250 struct radix_tree_root pinned_radix;
252 struct radix_tree_root dev_radix; 251 struct radix_tree_root dev_radix;
252
253 u64 extent_tree_insert[BTRFS_MAX_LEVEL * 3];
254 int extent_tree_insert_nr;
255 u64 extent_tree_prealloc[BTRFS_MAX_LEVEL * 3];
256 int extent_tree_prealloc_nr;
257
253 u64 generation; 258 u64 generation;
254 struct btrfs_transaction *running_transaction; 259 struct btrfs_transaction *running_transaction;
255 struct btrfs_super_block *disk_super; 260 struct btrfs_super_block *disk_super;
@@ -267,8 +272,7 @@ struct btrfs_fs_info {
267 272
268/* 273/*
269 * in ram representation of the tree. extent_root is used for all allocations 274 * in ram representation of the tree. extent_root is used for all allocations
270 * and for the extent tree extent_root root. current_insert is used 275 * and for the extent tree extent_root root.
271 * only for the extent tree.
272 */ 276 */
273struct btrfs_root { 277struct btrfs_root {
274 struct buffer_head *node; 278 struct buffer_head *node;
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 7aff6bb55d91..956727f015a5 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -542,6 +542,8 @@ struct btrfs_root *open_ctree(struct super_block *sb)
542 fs_info->btree_inode->i_size = sb->s_bdev->bd_inode->i_size; 542 fs_info->btree_inode->i_size = sb->s_bdev->bd_inode->i_size;
543 fs_info->btree_inode->i_mapping->a_ops = &btree_aops; 543 fs_info->btree_inode->i_mapping->a_ops = &btree_aops;
544 fs_info->do_barriers = 1; 544 fs_info->do_barriers = 1;
545 fs_info->extent_tree_insert_nr = 0;
546 fs_info->extent_tree_prealloc_nr = 0;
545 BTRFS_I(fs_info->btree_inode)->root = tree_root; 547 BTRFS_I(fs_info->btree_inode)->root = tree_root;
546 memset(&BTRFS_I(fs_info->btree_inode)->location, 0, 548 memset(&BTRFS_I(fs_info->btree_inode)->location, 0,
547 sizeof(struct btrfs_key)); 549 sizeof(struct btrfs_key));
@@ -555,7 +557,6 @@ struct btrfs_root *open_ctree(struct super_block *sb)
555 } 557 }
556 mutex_init(&fs_info->trans_mutex); 558 mutex_init(&fs_info->trans_mutex);
557 mutex_init(&fs_info->fs_mutex); 559 mutex_init(&fs_info->fs_mutex);
558 memset(&fs_info->current_insert, 0, sizeof(fs_info->current_insert));
559 memset(&fs_info->last_insert, 0, sizeof(fs_info->last_insert)); 560 memset(&fs_info->last_insert, 0, sizeof(fs_info->last_insert));
560 561
561 __setup_root(sb->s_blocksize, dev_root, 562 __setup_root(sb->s_blocksize, dev_root,
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 116519503d0c..e6fe3fd38819 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -169,9 +169,8 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
169 btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY); 169 btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY);
170 btrfs_set_extent_owner(&extent_item, extent_root->root_key.objectid); 170 btrfs_set_extent_owner(&extent_item, extent_root->root_key.objectid);
171 171
172 for (i = 0; i < extent_root->fs_info->current_insert.flags; i++) { 172 for (i = 0; i < extent_root->fs_info->extent_tree_insert_nr; i++) {
173 ins.objectid = extent_root->fs_info->current_insert.objectid + 173 ins.objectid = extent_root->fs_info->extent_tree_insert[i];
174 i;
175 super_blocks_used = btrfs_super_blocks_used(info->disk_super); 174 super_blocks_used = btrfs_super_blocks_used(info->disk_super);
176 btrfs_set_super_blocks_used(info->disk_super, 175 btrfs_set_super_blocks_used(info->disk_super,
177 super_blocks_used + 1); 176 super_blocks_used + 1);
@@ -179,7 +178,8 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
179 sizeof(extent_item)); 178 sizeof(extent_item));
180 BUG_ON(ret); 179 BUG_ON(ret);
181 } 180 }
182 extent_root->fs_info->current_insert.offset = 0; 181 extent_root->fs_info->extent_tree_insert_nr = 0;
182 extent_root->fs_info->extent_tree_prealloc_nr = 0;
183 return 0; 183 return 0;
184} 184}
185 185
@@ -349,7 +349,10 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
349 int start_found; 349 int start_found;
350 struct btrfs_leaf *l; 350 struct btrfs_leaf *l;
351 struct btrfs_root * root = orig_root->fs_info->extent_root; 351 struct btrfs_root * root = orig_root->fs_info->extent_root;
352 struct btrfs_fs_info *info = root->fs_info;
352 int total_needed = num_blocks; 353 int total_needed = num_blocks;
354 int total_found = 0;
355 int fill_prealloc = 0;
353 int level; 356 int level;
354 357
355 path = btrfs_alloc_path(); 358 path = btrfs_alloc_path();
@@ -357,8 +360,12 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
357 btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY); 360 btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY);
358 361
359 level = btrfs_header_level(btrfs_buffer_header(root->node)); 362 level = btrfs_header_level(btrfs_buffer_header(root->node));
360 total_needed += (level + 2) * 3; 363 if (num_blocks == 0) {
361 if (root->fs_info->last_insert.objectid == 0 && search_end == (u64)-1) { 364 fill_prealloc = 1;
365 num_blocks = 1;
366 total_needed = min(level + 2, BTRFS_MAX_LEVEL) * 3;
367 }
368 if (info->last_insert.objectid == 0 && search_end == (u64)-1) {
362 struct btrfs_disk_key *last_key; 369 struct btrfs_disk_key *last_key;
363 btrfs_init_path(path); 370 btrfs_init_path(path);
364 ins->objectid = (u64)-1; 371 ins->objectid = (u64)-1;
@@ -373,8 +380,8 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
373 last_key = &l->items[path->slots[0]].key; 380 last_key = &l->items[path->slots[0]].key;
374 search_start = btrfs_disk_key_objectid(last_key); 381 search_start = btrfs_disk_key_objectid(last_key);
375 } 382 }
376 if (root->fs_info->last_insert.objectid > search_start) 383 if (info->last_insert.objectid > search_start)
377 search_start = root->fs_info->last_insert.objectid; 384 search_start = info->last_insert.objectid;
378 385
379check_failed: 386check_failed:
380 btrfs_init_path(path); 387 btrfs_init_path(path);
@@ -392,6 +399,10 @@ check_failed:
392 l = btrfs_buffer_leaf(path->nodes[0]); 399 l = btrfs_buffer_leaf(path->nodes[0]);
393 slot = path->slots[0]; 400 slot = path->slots[0];
394 if (slot >= btrfs_header_nritems(&l->header)) { 401 if (slot >= btrfs_header_nritems(&l->header)) {
402 if (fill_prealloc) {
403 info->extent_tree_prealloc_nr = 0;
404 total_found = 0;
405 }
395 ret = btrfs_next_leaf(root, path); 406 ret = btrfs_next_leaf(root, path);
396 if (ret == 0) 407 if (ret == 0)
397 continue; 408 continue;
@@ -399,13 +410,13 @@ check_failed:
399 goto error; 410 goto error;
400 if (!start_found) { 411 if (!start_found) {
401 ins->objectid = search_start; 412 ins->objectid = search_start;
402 ins->offset = (u64)-1; 413 ins->offset = (u64)-1 - search_start;
403 start_found = 1; 414 start_found = 1;
404 goto check_pending; 415 goto check_pending;
405 } 416 }
406 ins->objectid = last_block > search_start ? 417 ins->objectid = last_block > search_start ?
407 last_block : search_start; 418 last_block : search_start;
408 ins->offset = (u64)-1; 419 ins->offset = (u64)-1 - ins->objectid;
409 goto check_pending; 420 goto check_pending;
410 } 421 }
411 btrfs_disk_key_to_cpu(&key, &l->items[slot].key); 422 btrfs_disk_key_to_cpu(&key, &l->items[slot].key);
@@ -414,7 +425,7 @@ check_failed:
414 if (last_block < search_start) 425 if (last_block < search_start)
415 last_block = search_start; 426 last_block = search_start;
416 hole_size = key.objectid - last_block; 427 hole_size = key.objectid - last_block;
417 if (hole_size > total_needed) { 428 if (hole_size > num_blocks) {
418 ins->objectid = last_block; 429 ins->objectid = last_block;
419 ins->offset = hole_size; 430 ins->offset = hole_size;
420 goto check_pending; 431 goto check_pending;
@@ -433,17 +444,51 @@ check_pending:
433 btrfs_release_path(root, path); 444 btrfs_release_path(root, path);
434 BUG_ON(ins->objectid < search_start); 445 BUG_ON(ins->objectid < search_start);
435 for (test_block = ins->objectid; 446 for (test_block = ins->objectid;
436 test_block < ins->objectid + total_needed; test_block++) { 447 test_block < ins->objectid + num_blocks; test_block++) {
437 if (test_radix_bit(&root->fs_info->pinned_radix, 448 if (test_radix_bit(&info->pinned_radix, test_block)) {
438 test_block)) {
439 search_start = test_block + 1; 449 search_start = test_block + 1;
440 goto check_failed; 450 goto check_failed;
441 } 451 }
442 } 452 }
443 BUG_ON(root->fs_info->current_insert.offset); 453 if (!fill_prealloc && info->extent_tree_insert_nr) {
444 root->fs_info->current_insert.offset = total_needed - num_blocks; 454 u64 last =
445 root->fs_info->current_insert.objectid = ins->objectid + num_blocks; 455 info->extent_tree_insert[info->extent_tree_insert_nr - 1];
446 root->fs_info->current_insert.flags = 0; 456 if (ins->objectid + num_blocks >
457 info->extent_tree_insert[0] &&
458 ins->objectid <= last) {
459 search_start = last + 1;
460 WARN_ON(1);
461 goto check_failed;
462 }
463 }
464 if (!fill_prealloc && info->extent_tree_prealloc_nr) {
465 u64 first =
466 info->extent_tree_prealloc[info->extent_tree_prealloc_nr - 1];
467 if (ins->objectid + num_blocks > first &&
468 ins->objectid <= info->extent_tree_prealloc[0]) {
469 search_start = info->extent_tree_prealloc[0] + 1;
470 WARN_ON(1);
471 goto check_failed;
472 }
473 }
474 if (fill_prealloc) {
475 int nr;
476 test_block = ins->objectid;
477 while(test_block < ins->objectid + ins->offset &&
478 total_found < total_needed) {
479 nr = total_needed - total_found - 1;
480 BUG_ON(nr < 0);
481 root->fs_info->extent_tree_prealloc[nr] =
482 test_block;
483 total_found++;
484 test_block++;
485 }
486 if (total_found < total_needed) {
487 search_start = test_block;
488 goto check_failed;
489 }
490 root->fs_info->extent_tree_prealloc_nr = total_found;
491 }
447 root->fs_info->last_insert.objectid = ins->objectid; 492 root->fs_info->last_insert.objectid = ins->objectid;
448 ins->offset = num_blocks; 493 ins->offset = num_blocks;
449 btrfs_free_path(path); 494 btrfs_free_path(path);
@@ -472,25 +517,35 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
472 struct btrfs_fs_info *info = root->fs_info; 517 struct btrfs_fs_info *info = root->fs_info;
473 struct btrfs_root *extent_root = info->extent_root; 518 struct btrfs_root *extent_root = info->extent_root;
474 struct btrfs_extent_item extent_item; 519 struct btrfs_extent_item extent_item;
520 struct btrfs_key prealloc_key;
475 521
476 btrfs_set_extent_refs(&extent_item, 1); 522 btrfs_set_extent_refs(&extent_item, 1);
477 btrfs_set_extent_owner(&extent_item, owner); 523 btrfs_set_extent_owner(&extent_item, owner);
478 524
479 if (root == extent_root) { 525 if (root == extent_root) {
480 BUG_ON(extent_root->fs_info->current_insert.offset == 0); 526 int nr;
527 BUG_ON(info->extent_tree_prealloc_nr == 0);
481 BUG_ON(num_blocks != 1); 528 BUG_ON(num_blocks != 1);
482 BUG_ON(extent_root->fs_info->current_insert.flags ==
483 extent_root->fs_info->current_insert.offset);
484 ins->offset = 1; 529 ins->offset = 1;
485 ins->objectid = extent_root->fs_info->current_insert.objectid + 530 info->extent_tree_prealloc_nr--;
486 extent_root->fs_info->current_insert.flags++; 531 nr = info->extent_tree_prealloc_nr;
532 ins->objectid = info->extent_tree_prealloc[nr];
533 info->extent_tree_insert[info->extent_tree_insert_nr++] =
534 ins->objectid;
487 return 0; 535 return 0;
488 } 536 }
537 /* do the real allocation */
489 ret = find_free_extent(trans, root, num_blocks, search_start, 538 ret = find_free_extent(trans, root, num_blocks, search_start,
490 search_end, ins); 539 search_end, ins);
491 if (ret) 540 if (ret)
492 return ret; 541 return ret;
493 542
543 /* then do prealloc for the extent tree */
544 ret = find_free_extent(trans, root, 0, ins->objectid + ins->offset,
545 search_end, &prealloc_key);
546 if (ret)
547 return ret;
548
494 super_blocks_used = btrfs_super_blocks_used(info->disk_super); 549 super_blocks_used = btrfs_super_blocks_used(info->disk_super);
495 btrfs_set_super_blocks_used(info->disk_super, super_blocks_used + 550 btrfs_set_super_blocks_used(info->disk_super, super_blocks_used +
496 num_blocks); 551 num_blocks);