aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-06-22 14:16:25 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-06-22 14:16:25 -0400
commit54aa1f4dfdacd60a19c4471220b24e581be6f774 (patch)
tree1462277822cc63c00ad31b522457363a5c6be6ab /fs/btrfs/extent-tree.c
parent11bd143fc8243cf48c934dc1c4479a5aacf58ce3 (diff)
Btrfs: Audit callers and return codes to make sure -ENOSPC gets up the stack
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c141
1 files changed, 115 insertions, 26 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index b38c3e92f0c8..8025e9f8ef19 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -100,6 +100,8 @@ static int cache_block_group(struct btrfs_root *root,
100 if (slot >= btrfs_header_nritems(&leaf->header)) { 100 if (slot >= btrfs_header_nritems(&leaf->header)) {
101 reada_extent_leaves(root, path, limit); 101 reada_extent_leaves(root, path, limit);
102 ret = btrfs_next_leaf(root, path); 102 ret = btrfs_next_leaf(root, path);
103 if (ret < 0)
104 goto err;
103 if (ret == 0) { 105 if (ret == 0) {
104 continue; 106 continue;
105 } else { 107 } else {
@@ -148,6 +150,7 @@ static int cache_block_group(struct btrfs_root *root,
148 } 150 }
149 151
150 block_group->cached = 1; 152 block_group->cached = 1;
153err:
151 btrfs_free_path(path); 154 btrfs_free_path(path);
152 return 0; 155 return 0;
153} 156}
@@ -201,7 +204,9 @@ static u64 find_search_start(struct btrfs_root *root,
201 last = max(last, cache->last_prealloc); 204 last = max(last, cache->last_prealloc);
202 } 205 }
203again: 206again:
204 cache_block_group(root, cache); 207 ret = cache_block_group(root, cache);
208 if (ret)
209 goto out;
205 while(1) { 210 while(1) {
206 ret = find_first_radix_bit(&root->fs_info->extent_map_radix, 211 ret = find_first_radix_bit(&root->fs_info->extent_map_radix,
207 gang, last, ARRAY_SIZE(gang)); 212 gang, last, ARRAY_SIZE(gang));
@@ -398,16 +403,23 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
398 struct btrfs_key ins; 403 struct btrfs_key ins;
399 u32 refs; 404 u32 refs;
400 405
401 find_free_extent(trans, root->fs_info->extent_root, 0, 0, (u64)-1, 0,
402 &ins, 0);
403 path = btrfs_alloc_path(); 406 path = btrfs_alloc_path();
404 BUG_ON(!path); 407 if (!path)
408 return -ENOMEM;
409 ret = find_free_extent(trans, root->fs_info->extent_root, 0, 0,
410 (u64)-1, 0, &ins, 0);
411 if (ret) {
412 btrfs_free_path(path);
413 return ret;
414 }
405 key.objectid = blocknr; 415 key.objectid = blocknr;
406 key.flags = 0; 416 key.flags = 0;
407 btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); 417 btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
408 key.offset = num_blocks; 418 key.offset = num_blocks;
409 ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, path, 419 ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, path,
410 0, 1); 420 0, 1);
421 if (ret < 0)
422 return ret;
411 if (ret != 0) { 423 if (ret != 0) {
412 BUG(); 424 BUG();
413 } 425 }
@@ -442,12 +454,14 @@ static int lookup_extent_ref(struct btrfs_trans_handle *trans,
442 btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); 454 btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
443 ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, path, 455 ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, path,
444 0, 0); 456 0, 0);
457 if (ret < 0)
458 goto out;
445 if (ret != 0) 459 if (ret != 0)
446 BUG(); 460 BUG();
447 l = btrfs_buffer_leaf(path->nodes[0]); 461 l = btrfs_buffer_leaf(path->nodes[0]);
448 item = btrfs_item_ptr(l, path->slots[0], struct btrfs_extent_item); 462 item = btrfs_item_ptr(l, path->slots[0], struct btrfs_extent_item);
449 *refs = btrfs_extent_refs(item); 463 *refs = btrfs_extent_refs(item);
450 btrfs_release_path(root->fs_info->extent_root, path); 464out:
451 btrfs_free_path(path); 465 btrfs_free_path(path);
452 return 0; 466 return 0;
453} 467}
@@ -469,6 +483,8 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
469 int i; 483 int i;
470 int leaf; 484 int leaf;
471 int ret; 485 int ret;
486 int faili;
487 int err;
472 488
473 if (!root->ref_cows) 489 if (!root->ref_cows)
474 return 0; 490 return 0;
@@ -491,14 +507,45 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
491 continue; 507 continue;
492 ret = btrfs_inc_extent_ref(trans, root, disk_blocknr, 508 ret = btrfs_inc_extent_ref(trans, root, disk_blocknr,
493 btrfs_file_extent_disk_num_blocks(fi)); 509 btrfs_file_extent_disk_num_blocks(fi));
494 BUG_ON(ret); 510 if (ret) {
511 faili = i;
512 goto fail;
513 }
495 } else { 514 } else {
496 blocknr = btrfs_node_blockptr(buf_node, i); 515 blocknr = btrfs_node_blockptr(buf_node, i);
497 ret = btrfs_inc_extent_ref(trans, root, blocknr, 1); 516 ret = btrfs_inc_extent_ref(trans, root, blocknr, 1);
498 BUG_ON(ret); 517 if (ret) {
518 faili = i;
519 goto fail;
520 }
499 } 521 }
500 } 522 }
501 return 0; 523 return 0;
524fail:
525 for (i =0; i < faili; i++) {
526 if (leaf) {
527 u64 disk_blocknr;
528 key = &buf_leaf->items[i].key;
529 if (btrfs_disk_key_type(key) != BTRFS_EXTENT_DATA_KEY)
530 continue;
531 fi = btrfs_item_ptr(buf_leaf, i,
532 struct btrfs_file_extent_item);
533 if (btrfs_file_extent_type(fi) ==
534 BTRFS_FILE_EXTENT_INLINE)
535 continue;
536 disk_blocknr = btrfs_file_extent_disk_blocknr(fi);
537 if (disk_blocknr == 0)
538 continue;
539 err = btrfs_free_extent(trans, root, disk_blocknr,
540 btrfs_file_extent_disk_num_blocks(fi), 0);
541 BUG_ON(err);
542 } else {
543 blocknr = btrfs_node_blockptr(buf_node, i);
544 err = btrfs_free_extent(trans, root, blocknr, 1, 0);
545 BUG_ON(err);
546 }
547 }
548 return ret;
502} 549}
503 550
504static int write_one_cache_group(struct btrfs_trans_handle *trans, 551static int write_one_cache_group(struct btrfs_trans_handle *trans,
@@ -512,15 +559,20 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans,
512 struct btrfs_block_group_item *bi; 559 struct btrfs_block_group_item *bi;
513 struct btrfs_key ins; 560 struct btrfs_key ins;
514 561
515 find_free_extent(trans, extent_root, 0, 0, (u64)-1, 0, &ins, 0); 562 ret = find_free_extent(trans, extent_root, 0, 0, (u64)-1, 0, &ins, 0);
563 /* FIXME, set bit to recalc cache groups on next mount */
564 if (ret)
565 return ret;
516 ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1); 566 ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1);
567 if (ret < 0)
568 goto fail;
517 BUG_ON(ret); 569 BUG_ON(ret);
518 bi = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], 570 bi = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0],
519 struct btrfs_block_group_item); 571 struct btrfs_block_group_item);
520 memcpy(bi, &cache->item, sizeof(*bi)); 572 memcpy(bi, &cache->item, sizeof(*bi));
521 mark_buffer_dirty(path->nodes[0]); 573 mark_buffer_dirty(path->nodes[0]);
522 btrfs_release_path(extent_root, path); 574 btrfs_release_path(extent_root, path);
523 575fail:
524 finish_current_insert(trans, extent_root); 576 finish_current_insert(trans, extent_root);
525 pending_ret = del_pending_extents(trans, extent_root); 577 pending_ret = del_pending_extents(trans, extent_root);
526 if (ret) 578 if (ret)
@@ -543,6 +595,7 @@ static int write_dirty_block_radix(struct btrfs_trans_handle *trans,
543 int werr = 0; 595 int werr = 0;
544 int i; 596 int i;
545 struct btrfs_path *path; 597 struct btrfs_path *path;
598 unsigned long off = 0;
546 599
547 path = btrfs_alloc_path(); 600 path = btrfs_alloc_path();
548 if (!path) 601 if (!path)
@@ -550,18 +603,28 @@ static int write_dirty_block_radix(struct btrfs_trans_handle *trans,
550 603
551 while(1) { 604 while(1) {
552 ret = radix_tree_gang_lookup_tag(radix, (void **)cache, 605 ret = radix_tree_gang_lookup_tag(radix, (void **)cache,
553 0, ARRAY_SIZE(cache), 606 off, ARRAY_SIZE(cache),
554 BTRFS_BLOCK_GROUP_DIRTY); 607 BTRFS_BLOCK_GROUP_DIRTY);
555 if (!ret) 608 if (!ret)
556 break; 609 break;
557 for (i = 0; i < ret; i++) { 610 for (i = 0; i < ret; i++) {
558 radix_tree_tag_clear(radix, cache[i]->key.objectid +
559 cache[i]->key.offset - 1,
560 BTRFS_BLOCK_GROUP_DIRTY);
561 err = write_one_cache_group(trans, root, 611 err = write_one_cache_group(trans, root,
562 path, cache[i]); 612 path, cache[i]);
563 if (err) 613 /*
614 * if we fail to write the cache group, we want
615 * to keep it marked dirty in hopes that a later
616 * write will work
617 */
618 if (err) {
564 werr = err; 619 werr = err;
620 off = cache[i]->key.objectid +
621 cache[i]->key.offset;
622 continue;
623 }
624
625 radix_tree_tag_clear(radix, cache[i]->key.objectid +
626 cache[i]->key.offset - 1,
627 BTRFS_BLOCK_GROUP_DIRTY);
565 } 628 }
566 } 629 }
567 btrfs_free_path(path); 630 btrfs_free_path(path);
@@ -801,14 +864,20 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
801 btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); 864 btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
802 key.offset = num_blocks; 865 key.offset = num_blocks;
803 866
804 find_free_extent(trans, root, 0, 0, (u64)-1, 0, &ins, 0);
805 path = btrfs_alloc_path(); 867 path = btrfs_alloc_path();
806 BUG_ON(!path); 868 if (!path)
869 return -ENOMEM;
807 870
808 ret = btrfs_search_slot(trans, extent_root, &key, path, -1, 1); 871 ret = find_free_extent(trans, root, 0, 0, (u64)-1, 0, &ins, 0);
809 if (ret) { 872 if (ret) {
810 BUG(); 873 btrfs_free_path(path);
874 return ret;
811 } 875 }
876
877 ret = btrfs_search_slot(trans, extent_root, &key, path, -1, 1);
878 if (ret < 0)
879 return ret;
880 BUG_ON(ret);
812 ei = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], 881 ei = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0],
813 struct btrfs_extent_item); 882 struct btrfs_extent_item);
814 BUG_ON(ei->refs == 0); 883 BUG_ON(ei->refs == 0);
@@ -827,8 +896,9 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
827 btrfs_set_super_blocks_used(info->disk_super, 896 btrfs_set_super_blocks_used(info->disk_super,
828 super_blocks_used - num_blocks); 897 super_blocks_used - num_blocks);
829 ret = btrfs_del_item(trans, extent_root, path); 898 ret = btrfs_del_item(trans, extent_root, path);
830 if (ret) 899 if (ret) {
831 BUG(); 900 return ret;
901 }
832 ret = update_block_group(trans, root, blocknr, num_blocks, 0, 902 ret = update_block_group(trans, root, blocknr, num_blocks, 0,
833 mark_free, 0); 903 mark_free, 0);
834 BUG_ON(ret); 904 BUG_ON(ret);
@@ -1075,7 +1145,6 @@ next:
1075 path->slots[0]++; 1145 path->slots[0]++;
1076 cond_resched(); 1146 cond_resched();
1077 } 1147 }
1078 // FIXME -ENOSPC
1079check_pending: 1148check_pending:
1080 /* we have to make sure we didn't find an extent that has already 1149 /* we have to make sure we didn't find an extent that has already
1081 * been allocated by the map tree or the original allocation 1150 * been allocated by the map tree or the original allocation
@@ -1246,7 +1315,15 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1246 ret = find_free_extent(trans, root, num_blocks, search_start, 1315 ret = find_free_extent(trans, root, num_blocks, search_start,
1247 search_end, hint_block, ins, data); 1316 search_end, hint_block, ins, data);
1248 if (ret) { 1317 if (ret) {
1249 return ret; 1318 if (search_start == 0)
1319 return ret;
1320 search_end = search_start - 1;
1321 search_start = 0;
1322 hint_block = search_start;
1323 ret = find_free_extent(trans, root, num_blocks, search_start,
1324 search_end, hint_block, ins, data);
1325 if (ret)
1326 return ret;
1250 } 1327 }
1251 1328
1252 /* 1329 /*
@@ -1271,7 +1348,16 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1271 search_end, hint_block, 1348 search_end, hint_block,
1272 &prealloc_key, 0); 1349 &prealloc_key, 0);
1273 if (ret) { 1350 if (ret) {
1274 return ret; 1351 if (search_start == 0)
1352 return ret;
1353 search_end = search_start - 1;
1354 search_start = 0;
1355 hint_block = search_start;
1356 ret = find_free_extent(trans, root, 0, search_start,
1357 search_end, hint_block,
1358 &prealloc_key, 0);
1359 if (ret)
1360 return ret;
1275 } 1361 }
1276 } 1362 }
1277 1363
@@ -1309,11 +1395,14 @@ struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
1309 ret = btrfs_alloc_extent(trans, root, root->root_key.objectid, 1395 ret = btrfs_alloc_extent(trans, root, root->root_key.objectid,
1310 1, hint, (unsigned long)-1, &ins, 0); 1396 1, hint, (unsigned long)-1, &ins, 0);
1311 if (ret) { 1397 if (ret) {
1312 BUG(); 1398 BUG_ON(ret > 0);
1313 return NULL; 1399 return ERR_PTR(ret);
1314 } 1400 }
1315 BUG_ON(ret);
1316 buf = btrfs_find_create_tree_block(root, ins.objectid); 1401 buf = btrfs_find_create_tree_block(root, ins.objectid);
1402 if (!buf) {
1403 btrfs_free_extent(trans, root, ins.objectid, 1, 0);
1404 return ERR_PTR(-ENOMEM);
1405 }
1317 set_buffer_uptodate(buf); 1406 set_buffer_uptodate(buf);
1318 set_buffer_checked(buf); 1407 set_buffer_checked(buf);
1319 set_radix_bit(&trans->transaction->dirty_pages, buf->b_page->index); 1408 set_radix_bit(&trans->transaction->dirty_pages, buf->b_page->index);