diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-06-22 14:16:25 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-06-22 14:16:25 -0400 |
commit | 54aa1f4dfdacd60a19c4471220b24e581be6f774 (patch) | |
tree | 1462277822cc63c00ad31b522457363a5c6be6ab | |
parent | 11bd143fc8243cf48c934dc1c4479a5aacf58ce3 (diff) |
Btrfs: Audit callers and return codes to make sure -ENOSPC gets up the stack
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r-- | fs/btrfs/ctree.c | 106 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 3 | ||||
-rw-r--r-- | fs/btrfs/dir-item.c | 6 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 2 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 141 | ||||
-rw-r--r-- | fs/btrfs/file-item.c | 46 | ||||
-rw-r--r-- | fs/btrfs/file.c | 131 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 165 | ||||
-rw-r--r-- | fs/btrfs/root-tree.c | 1 | ||||
-rw-r--r-- | fs/btrfs/super.c | 3 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 21 |
11 files changed, 410 insertions, 215 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 498dea0854c1..606a19b5916d 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -73,6 +73,7 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root | |||
73 | { | 73 | { |
74 | struct buffer_head *cow; | 74 | struct buffer_head *cow; |
75 | struct btrfs_node *cow_node; | 75 | struct btrfs_node *cow_node; |
76 | int ret; | ||
76 | 77 | ||
77 | if (btrfs_header_generation(btrfs_buffer_header(buf)) == | 78 | if (btrfs_header_generation(btrfs_buffer_header(buf)) == |
78 | trans->transid) { | 79 | trans->transid) { |
@@ -80,6 +81,8 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root | |||
80 | return 0; | 81 | return 0; |
81 | } | 82 | } |
82 | cow = btrfs_alloc_free_block(trans, root, buf->b_blocknr); | 83 | cow = btrfs_alloc_free_block(trans, root, buf->b_blocknr); |
84 | if (IS_ERR(cow)) | ||
85 | return PTR_ERR(cow); | ||
83 | cow_node = btrfs_buffer_node(cow); | 86 | cow_node = btrfs_buffer_node(cow); |
84 | if (buf->b_size != root->blocksize || cow->b_size != root->blocksize) | 87 | if (buf->b_size != root->blocksize || cow->b_size != root->blocksize) |
85 | WARN_ON(1); | 88 | WARN_ON(1); |
@@ -87,7 +90,9 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root | |||
87 | btrfs_set_header_blocknr(&cow_node->header, bh_blocknr(cow)); | 90 | btrfs_set_header_blocknr(&cow_node->header, bh_blocknr(cow)); |
88 | btrfs_set_header_generation(&cow_node->header, trans->transid); | 91 | btrfs_set_header_generation(&cow_node->header, trans->transid); |
89 | btrfs_set_header_owner(&cow_node->header, root->root_key.objectid); | 92 | btrfs_set_header_owner(&cow_node->header, root->root_key.objectid); |
90 | btrfs_inc_ref(trans, root, buf); | 93 | ret = btrfs_inc_ref(trans, root, buf); |
94 | if (ret) | ||
95 | return ret; | ||
91 | if (buf == root->node) { | 96 | if (buf == root->node) { |
92 | root->node = cow; | 97 | root->node = cow; |
93 | get_bh(cow); | 98 | get_bh(cow); |
@@ -320,6 +325,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
320 | int wret; | 325 | int wret; |
321 | int pslot; | 326 | int pslot; |
322 | int orig_slot = path->slots[level]; | 327 | int orig_slot = path->slots[level]; |
328 | int err_on_enospc = 0; | ||
323 | u64 orig_ptr; | 329 | u64 orig_ptr; |
324 | 330 | ||
325 | if (level == 0) | 331 | if (level == 0) |
@@ -363,29 +369,43 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
363 | BTRFS_NODEPTRS_PER_BLOCK(root) / 4) | 369 | BTRFS_NODEPTRS_PER_BLOCK(root) / 4) |
364 | return 0; | 370 | return 0; |
365 | 371 | ||
372 | if (btrfs_header_nritems(&mid->header) < 2) | ||
373 | err_on_enospc = 1; | ||
374 | |||
366 | left_buf = read_node_slot(root, parent_buf, pslot - 1); | 375 | left_buf = read_node_slot(root, parent_buf, pslot - 1); |
367 | right_buf = read_node_slot(root, parent_buf, pslot + 1); | 376 | right_buf = read_node_slot(root, parent_buf, pslot + 1); |
368 | 377 | ||
369 | /* first, try to make some room in the middle buffer */ | 378 | /* first, try to make some room in the middle buffer */ |
370 | if (left_buf) { | 379 | if (left_buf) { |
371 | btrfs_cow_block(trans, root, left_buf, parent_buf, pslot - 1, | 380 | wret = btrfs_cow_block(trans, root, left_buf, |
372 | &left_buf); | 381 | parent_buf, pslot - 1, &left_buf); |
382 | if (wret) { | ||
383 | ret = wret; | ||
384 | goto enospc; | ||
385 | } | ||
373 | left = btrfs_buffer_node(left_buf); | 386 | left = btrfs_buffer_node(left_buf); |
374 | orig_slot += btrfs_header_nritems(&left->header); | 387 | orig_slot += btrfs_header_nritems(&left->header); |
375 | wret = push_node_left(trans, root, left_buf, mid_buf); | 388 | wret = push_node_left(trans, root, left_buf, mid_buf); |
376 | if (wret < 0) | 389 | if (wret < 0) |
377 | ret = wret; | 390 | ret = wret; |
391 | if (btrfs_header_nritems(&mid->header) < 2) | ||
392 | err_on_enospc = 1; | ||
378 | } | 393 | } |
379 | 394 | ||
380 | /* | 395 | /* |
381 | * then try to empty the right most buffer into the middle | 396 | * then try to empty the right most buffer into the middle |
382 | */ | 397 | */ |
383 | if (right_buf) { | 398 | if (right_buf) { |
384 | btrfs_cow_block(trans, root, right_buf, parent_buf, pslot + 1, | 399 | wret = btrfs_cow_block(trans, root, right_buf, |
385 | &right_buf); | 400 | parent_buf, pslot + 1, &right_buf); |
401 | if (wret) { | ||
402 | ret = wret; | ||
403 | goto enospc; | ||
404 | } | ||
405 | |||
386 | right = btrfs_buffer_node(right_buf); | 406 | right = btrfs_buffer_node(right_buf); |
387 | wret = push_node_left(trans, root, mid_buf, right_buf); | 407 | wret = push_node_left(trans, root, mid_buf, right_buf); |
388 | if (wret < 0) | 408 | if (wret < 0 && wret != -ENOSPC) |
389 | ret = wret; | 409 | ret = wret; |
390 | if (btrfs_header_nritems(&right->header) == 0) { | 410 | if (btrfs_header_nritems(&right->header) == 0) { |
391 | u64 blocknr = bh_blocknr(right_buf); | 411 | u64 blocknr = bh_blocknr(right_buf); |
@@ -421,8 +441,10 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
421 | */ | 441 | */ |
422 | BUG_ON(!left_buf); | 442 | BUG_ON(!left_buf); |
423 | wret = balance_node_right(trans, root, mid_buf, left_buf); | 443 | wret = balance_node_right(trans, root, mid_buf, left_buf); |
424 | if (wret < 0) | 444 | if (wret < 0) { |
425 | ret = wret; | 445 | ret = wret; |
446 | goto enospc; | ||
447 | } | ||
426 | BUG_ON(wret == 1); | 448 | BUG_ON(wret == 1); |
427 | } | 449 | } |
428 | if (btrfs_header_nritems(&mid->header) == 0) { | 450 | if (btrfs_header_nritems(&mid->header) == 0) { |
@@ -467,7 +489,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
467 | btrfs_node_blockptr(btrfs_buffer_node(path->nodes[level]), | 489 | btrfs_node_blockptr(btrfs_buffer_node(path->nodes[level]), |
468 | path->slots[level])) | 490 | path->slots[level])) |
469 | BUG(); | 491 | BUG(); |
470 | 492 | enospc: | |
471 | if (right_buf) | 493 | if (right_buf) |
472 | btrfs_block_release(root, right_buf); | 494 | btrfs_block_release(root, right_buf); |
473 | if (left_buf) | 495 | if (left_buf) |
@@ -519,10 +541,15 @@ static int push_nodes_for_insert(struct btrfs_trans_handle *trans, | |||
519 | if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) { | 541 | if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) { |
520 | wret = 1; | 542 | wret = 1; |
521 | } else { | 543 | } else { |
522 | btrfs_cow_block(trans, root, left_buf, parent_buf, | 544 | ret = btrfs_cow_block(trans, root, left_buf, parent_buf, |
523 | pslot - 1, &left_buf); | 545 | pslot - 1, &left_buf); |
524 | left = btrfs_buffer_node(left_buf); | 546 | if (ret) |
525 | wret = push_node_left(trans, root, left_buf, mid_buf); | 547 | wret = 1; |
548 | else { | ||
549 | left = btrfs_buffer_node(left_buf); | ||
550 | wret = push_node_left(trans, root, | ||
551 | left_buf, mid_buf); | ||
552 | } | ||
526 | } | 553 | } |
527 | if (wret < 0) | 554 | if (wret < 0) |
528 | ret = wret; | 555 | ret = wret; |
@@ -561,11 +588,16 @@ static int push_nodes_for_insert(struct btrfs_trans_handle *trans, | |||
561 | if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) { | 588 | if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(root) - 1) { |
562 | wret = 1; | 589 | wret = 1; |
563 | } else { | 590 | } else { |
564 | btrfs_cow_block(trans, root, right_buf, | 591 | ret = btrfs_cow_block(trans, root, right_buf, |
565 | parent_buf, pslot + 1, &right_buf); | 592 | parent_buf, pslot + 1, |
566 | right = btrfs_buffer_node(right_buf); | 593 | &right_buf); |
567 | wret = balance_node_right(trans, root, | 594 | if (ret) |
568 | right_buf, mid_buf); | 595 | wret = 1; |
596 | else { | ||
597 | right = btrfs_buffer_node(right_buf); | ||
598 | wret = balance_node_right(trans, root, | ||
599 | right_buf, mid_buf); | ||
600 | } | ||
569 | } | 601 | } |
570 | if (wret < 0) | 602 | if (wret < 0) |
571 | ret = wret; | 603 | ret = wret; |
@@ -631,6 +663,10 @@ again: | |||
631 | p->nodes[level + 1], | 663 | p->nodes[level + 1], |
632 | p->slots[level + 1], | 664 | p->slots[level + 1], |
633 | &cow_buf); | 665 | &cow_buf); |
666 | if (wret) { | ||
667 | btrfs_block_release(root, cow_buf); | ||
668 | return wret; | ||
669 | } | ||
634 | b = cow_buf; | 670 | b = cow_buf; |
635 | c = btrfs_buffer_node(b); | 671 | c = btrfs_buffer_node(b); |
636 | } | 672 | } |
@@ -737,6 +773,7 @@ static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
737 | src_nritems = btrfs_header_nritems(&src->header); | 773 | src_nritems = btrfs_header_nritems(&src->header); |
738 | dst_nritems = btrfs_header_nritems(&dst->header); | 774 | dst_nritems = btrfs_header_nritems(&dst->header); |
739 | push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems; | 775 | push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems; |
776 | |||
740 | if (push_items <= 0) { | 777 | if (push_items <= 0) { |
741 | return 1; | 778 | return 1; |
742 | } | 779 | } |
@@ -827,6 +864,8 @@ static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root | |||
827 | BUG_ON(path->nodes[level-1] != root->node); | 864 | BUG_ON(path->nodes[level-1] != root->node); |
828 | 865 | ||
829 | t = btrfs_alloc_free_block(trans, root, root->node->b_blocknr); | 866 | t = btrfs_alloc_free_block(trans, root, root->node->b_blocknr); |
867 | if (IS_ERR(t)) | ||
868 | return PTR_ERR(t); | ||
830 | c = btrfs_buffer_node(t); | 869 | c = btrfs_buffer_node(t); |
831 | memset(c, 0, root->blocksize); | 870 | memset(c, 0, root->blocksize); |
832 | btrfs_set_header_nritems(&c->header, 1); | 871 | btrfs_set_header_nritems(&c->header, 1); |
@@ -929,10 +968,15 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root | |||
929 | btrfs_header_nritems(&c->header) < | 968 | btrfs_header_nritems(&c->header) < |
930 | BTRFS_NODEPTRS_PER_BLOCK(root) - 1) | 969 | BTRFS_NODEPTRS_PER_BLOCK(root) - 1) |
931 | return 0; | 970 | return 0; |
971 | if (ret < 0) | ||
972 | return ret; | ||
932 | } | 973 | } |
933 | 974 | ||
934 | c_nritems = btrfs_header_nritems(&c->header); | 975 | c_nritems = btrfs_header_nritems(&c->header); |
935 | split_buffer = btrfs_alloc_free_block(trans, root, t->b_blocknr); | 976 | split_buffer = btrfs_alloc_free_block(trans, root, t->b_blocknr); |
977 | if (IS_ERR(split_buffer)) | ||
978 | return PTR_ERR(split_buffer); | ||
979 | |||
936 | split = btrfs_buffer_node(split_buffer); | 980 | split = btrfs_buffer_node(split_buffer); |
937 | btrfs_set_header_flags(&split->header, btrfs_header_flags(&c->header)); | 981 | btrfs_set_header_flags(&split->header, btrfs_header_flags(&c->header)); |
938 | btrfs_set_header_level(&split->header, btrfs_header_level(&c->header)); | 982 | btrfs_set_header_level(&split->header, btrfs_header_level(&c->header)); |
@@ -1022,6 +1066,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1022 | struct btrfs_item *item; | 1066 | struct btrfs_item *item; |
1023 | u32 left_nritems; | 1067 | u32 left_nritems; |
1024 | u32 right_nritems; | 1068 | u32 right_nritems; |
1069 | int ret; | ||
1025 | 1070 | ||
1026 | slot = path->slots[1]; | 1071 | slot = path->slots[1]; |
1027 | if (!path->nodes[1]) { | 1072 | if (!path->nodes[1]) { |
@@ -1041,7 +1086,12 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1041 | return 1; | 1086 | return 1; |
1042 | } | 1087 | } |
1043 | /* cow and double check */ | 1088 | /* cow and double check */ |
1044 | btrfs_cow_block(trans, root, right_buf, upper, slot + 1, &right_buf); | 1089 | ret = btrfs_cow_block(trans, root, right_buf, upper, |
1090 | slot + 1, &right_buf); | ||
1091 | if (ret) { | ||
1092 | btrfs_block_release(root, right_buf); | ||
1093 | return 1; | ||
1094 | } | ||
1045 | right = btrfs_buffer_leaf(right_buf); | 1095 | right = btrfs_buffer_leaf(right_buf); |
1046 | free_space = btrfs_leaf_free_space(root, right); | 1096 | free_space = btrfs_leaf_free_space(root, right); |
1047 | if (free_space < data_size + sizeof(struct btrfs_item)) { | 1097 | if (free_space < data_size + sizeof(struct btrfs_item)) { |
@@ -1162,7 +1212,11 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1162 | } | 1212 | } |
1163 | 1213 | ||
1164 | /* cow and double check */ | 1214 | /* cow and double check */ |
1165 | btrfs_cow_block(trans, root, t, path->nodes[1], slot - 1, &t); | 1215 | ret = btrfs_cow_block(trans, root, t, path->nodes[1], slot - 1, &t); |
1216 | if (ret) { | ||
1217 | /* we hit -ENOSPC, but it isn't fatal here */ | ||
1218 | return 1; | ||
1219 | } | ||
1166 | left = btrfs_buffer_leaf(t); | 1220 | left = btrfs_buffer_leaf(t); |
1167 | free_space = btrfs_leaf_free_space(root, left); | 1221 | free_space = btrfs_leaf_free_space(root, left); |
1168 | if (free_space < data_size + sizeof(struct btrfs_item)) { | 1222 | if (free_space < data_size + sizeof(struct btrfs_item)) { |
@@ -1309,8 +1363,11 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1309 | slot = path->slots[0]; | 1363 | slot = path->slots[0]; |
1310 | nritems = btrfs_header_nritems(&l->header); | 1364 | nritems = btrfs_header_nritems(&l->header); |
1311 | mid = (nritems + 1)/ 2; | 1365 | mid = (nritems + 1)/ 2; |
1366 | |||
1312 | right_buffer = btrfs_alloc_free_block(trans, root, l_buf->b_blocknr); | 1367 | right_buffer = btrfs_alloc_free_block(trans, root, l_buf->b_blocknr); |
1313 | BUG_ON(!right_buffer); | 1368 | if (IS_ERR(right_buffer)) |
1369 | return PTR_ERR(right_buffer); | ||
1370 | |||
1314 | right = btrfs_buffer_leaf(right_buffer); | 1371 | right = btrfs_buffer_leaf(right_buffer); |
1315 | memset(&right->header, 0, sizeof(right->header)); | 1372 | memset(&right->header, 0, sizeof(right->header)); |
1316 | btrfs_set_header_blocknr(&right->header, bh_blocknr(right_buffer)); | 1373 | btrfs_set_header_blocknr(&right->header, bh_blocknr(right_buffer)); |
@@ -1407,7 +1464,9 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1407 | if (!double_split) | 1464 | if (!double_split) |
1408 | return ret; | 1465 | return ret; |
1409 | right_buffer = btrfs_alloc_free_block(trans, root, l_buf->b_blocknr); | 1466 | right_buffer = btrfs_alloc_free_block(trans, root, l_buf->b_blocknr); |
1410 | BUG_ON(!right_buffer); | 1467 | if (IS_ERR(right_buffer)) |
1468 | return PTR_ERR(right_buffer); | ||
1469 | |||
1411 | right = btrfs_buffer_leaf(right_buffer); | 1470 | right = btrfs_buffer_leaf(right_buffer); |
1412 | memset(&right->header, 0, sizeof(right->header)); | 1471 | memset(&right->header, 0, sizeof(right->header)); |
1413 | btrfs_set_header_blocknr(&right->header, bh_blocknr(right_buffer)); | 1472 | btrfs_set_header_blocknr(&right->header, bh_blocknr(right_buffer)); |
@@ -1655,7 +1714,6 @@ int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1655 | ptr, data, data_size); | 1714 | ptr, data, data_size); |
1656 | btrfs_mark_buffer_dirty(path->nodes[0]); | 1715 | btrfs_mark_buffer_dirty(path->nodes[0]); |
1657 | } | 1716 | } |
1658 | btrfs_release_path(root, path); | ||
1659 | btrfs_free_path(path); | 1717 | btrfs_free_path(path); |
1660 | return ret; | 1718 | return ret; |
1661 | } | 1719 | } |
@@ -1775,12 +1833,12 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
1775 | slot = path->slots[1]; | 1833 | slot = path->slots[1]; |
1776 | get_bh(leaf_buf); | 1834 | get_bh(leaf_buf); |
1777 | wret = push_leaf_left(trans, root, path, 1); | 1835 | wret = push_leaf_left(trans, root, path, 1); |
1778 | if (wret < 0) | 1836 | if (wret < 0 && wret != -ENOSPC) |
1779 | ret = wret; | 1837 | ret = wret; |
1780 | if (path->nodes[0] == leaf_buf && | 1838 | if (path->nodes[0] == leaf_buf && |
1781 | btrfs_header_nritems(&leaf->header)) { | 1839 | btrfs_header_nritems(&leaf->header)) { |
1782 | wret = push_leaf_right(trans, root, path, 1); | 1840 | wret = push_leaf_right(trans, root, path, 1); |
1783 | if (wret < 0) | 1841 | if (wret < 0 && wret != -ENOSPC) |
1784 | ret = wret; | 1842 | ret = wret; |
1785 | } | 1843 | } |
1786 | if (btrfs_header_nritems(&leaf->header) == 0) { | 1844 | if (btrfs_header_nritems(&leaf->header) == 0) { |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 19a1d998fca7..77071f273977 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -1126,9 +1126,6 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, | |||
1126 | struct btrfs_root *root, | 1126 | struct btrfs_root *root, |
1127 | u64 objectid, u64 offset, | 1127 | u64 objectid, u64 offset, |
1128 | char *data, size_t len); | 1128 | char *data, size_t len); |
1129 | int btrfs_csum_verify_file_block(struct btrfs_root *root, | ||
1130 | u64 objectid, u64 offset, | ||
1131 | char *data, size_t len); | ||
1132 | struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans, | 1129 | struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans, |
1133 | struct btrfs_root *root, | 1130 | struct btrfs_root *root, |
1134 | struct btrfs_path *path, | 1131 | struct btrfs_path *path, |
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index ff10cf5a8422..d5db8bdea3d8 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c | |||
@@ -47,6 +47,8 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle | |||
47 | if (ret) | 47 | if (ret) |
48 | return ERR_PTR(ret); | 48 | return ERR_PTR(ret); |
49 | } | 49 | } |
50 | if (ret < 0) | ||
51 | return ERR_PTR(ret); | ||
50 | WARN_ON(ret > 0); | 52 | WARN_ON(ret > 0); |
51 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 53 | leaf = btrfs_buffer_leaf(path->nodes[0]); |
52 | item = leaf->items + path->slots[0]; | 54 | item = leaf->items + path->slots[0]; |
@@ -225,14 +227,13 @@ int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans, | |||
225 | struct btrfs_leaf *leaf; | 227 | struct btrfs_leaf *leaf; |
226 | u32 sub_item_len; | 228 | u32 sub_item_len; |
227 | u32 item_len; | 229 | u32 item_len; |
228 | int ret; | 230 | int ret = 0; |
229 | 231 | ||
230 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 232 | leaf = btrfs_buffer_leaf(path->nodes[0]); |
231 | sub_item_len = sizeof(*di) + btrfs_dir_name_len(di); | 233 | sub_item_len = sizeof(*di) + btrfs_dir_name_len(di); |
232 | item_len = btrfs_item_size(leaf->items + path->slots[0]); | 234 | item_len = btrfs_item_size(leaf->items + path->slots[0]); |
233 | if (sub_item_len == btrfs_item_size(leaf->items + path->slots[0])) { | 235 | if (sub_item_len == btrfs_item_size(leaf->items + path->slots[0])) { |
234 | ret = btrfs_del_item(trans, root, path); | 236 | ret = btrfs_del_item(trans, root, path); |
235 | BUG_ON(ret); | ||
236 | } else { | 237 | } else { |
237 | char *ptr = (char *)di; | 238 | char *ptr = (char *)di; |
238 | char *start = btrfs_item_ptr(leaf, path->slots[0], char); | 239 | char *start = btrfs_item_ptr(leaf, path->slots[0], char); |
@@ -240,7 +241,6 @@ int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans, | |||
240 | item_len - (ptr + sub_item_len - start)); | 241 | item_len - (ptr + sub_item_len - start)); |
241 | ret = btrfs_truncate_item(trans, root, path, | 242 | ret = btrfs_truncate_item(trans, root, path, |
242 | item_len - sub_item_len); | 243 | item_len - sub_item_len); |
243 | BUG_ON(ret); | ||
244 | } | 244 | } |
245 | return 0; | 245 | return 0; |
246 | } | 246 | } |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 3712e946f9c8..865a284aa06c 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -580,7 +580,7 @@ int close_ctree(struct btrfs_root *root) | |||
580 | btrfs_transaction_flush_work(root); | 580 | btrfs_transaction_flush_work(root); |
581 | mutex_lock(&fs_info->fs_mutex); | 581 | mutex_lock(&fs_info->fs_mutex); |
582 | trans = btrfs_start_transaction(root, 1); | 582 | trans = btrfs_start_transaction(root, 1); |
583 | btrfs_commit_transaction(trans, root); | 583 | ret = btrfs_commit_transaction(trans, root); |
584 | /* run commit again to drop the original snapshot */ | 584 | /* run commit again to drop the original snapshot */ |
585 | trans = btrfs_start_transaction(root, 1); | 585 | trans = btrfs_start_transaction(root, 1); |
586 | btrfs_commit_transaction(trans, root); | 586 | btrfs_commit_transaction(trans, root); |
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; |
153 | err: | ||
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 | } |
203 | again: | 206 | again: |
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); | 464 | out: |
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; |
524 | fail: | ||
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 | ||
504 | static int write_one_cache_group(struct btrfs_trans_handle *trans, | 551 | static 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 | 575 | fail: | |
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 | ||
1079 | check_pending: | 1148 | check_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); |
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index cf894f09f6c7..68859934ae25 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
@@ -45,6 +45,8 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, | |||
45 | 45 | ||
46 | ret = btrfs_insert_empty_item(trans, root, path, &file_key, | 46 | ret = btrfs_insert_empty_item(trans, root, path, &file_key, |
47 | sizeof(*item)); | 47 | sizeof(*item)); |
48 | if (ret < 0) | ||
49 | goto out; | ||
48 | BUG_ON(ret); | 50 | BUG_ON(ret); |
49 | item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], | 51 | item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], |
50 | struct btrfs_file_extent_item); | 52 | struct btrfs_file_extent_item); |
@@ -55,10 +57,9 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, | |||
55 | btrfs_set_file_extent_generation(item, trans->transid); | 57 | btrfs_set_file_extent_generation(item, trans->transid); |
56 | btrfs_set_file_extent_type(item, BTRFS_FILE_EXTENT_REG); | 58 | btrfs_set_file_extent_type(item, BTRFS_FILE_EXTENT_REG); |
57 | btrfs_mark_buffer_dirty(path->nodes[0]); | 59 | btrfs_mark_buffer_dirty(path->nodes[0]); |
58 | 60 | out: | |
59 | btrfs_release_path(root, path); | ||
60 | btrfs_free_path(path); | 61 | btrfs_free_path(path); |
61 | return 0; | 62 | return ret; |
62 | } | 63 | } |
63 | 64 | ||
64 | struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans, | 65 | struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans, |
@@ -213,6 +214,8 @@ insert: | |||
213 | csum_offset = 0; | 214 | csum_offset = 0; |
214 | ret = btrfs_insert_empty_item(trans, root, path, &file_key, | 215 | ret = btrfs_insert_empty_item(trans, root, path, &file_key, |
215 | BTRFS_CRC32_SIZE); | 216 | BTRFS_CRC32_SIZE); |
217 | if (ret < 0) | ||
218 | goto fail; | ||
216 | if (ret != 0) { | 219 | if (ret != 0) { |
217 | WARN_ON(1); | 220 | WARN_ON(1); |
218 | goto fail; | 221 | goto fail; |
@@ -261,40 +264,3 @@ int btrfs_csum_truncate(struct btrfs_trans_handle *trans, | |||
261 | return ret; | 264 | return ret; |
262 | } | 265 | } |
263 | 266 | ||
264 | int btrfs_csum_verify_file_block(struct btrfs_root *root, | ||
265 | u64 objectid, u64 offset, | ||
266 | char *data, size_t len) | ||
267 | { | ||
268 | int ret; | ||
269 | struct btrfs_key file_key; | ||
270 | struct btrfs_path *path; | ||
271 | struct btrfs_csum_item *item; | ||
272 | char result[BTRFS_CRC32_SIZE]; | ||
273 | |||
274 | path = btrfs_alloc_path(); | ||
275 | BUG_ON(!path); | ||
276 | file_key.objectid = objectid; | ||
277 | file_key.offset = offset; | ||
278 | file_key.flags = 0; | ||
279 | btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); | ||
280 | mutex_lock(&root->fs_info->fs_mutex); | ||
281 | |||
282 | item = btrfs_lookup_csum(NULL, root, path, objectid, offset, 0); | ||
283 | if (IS_ERR(item)) { | ||
284 | ret = PTR_ERR(item); | ||
285 | /* a csum that isn't present is a preallocated region. */ | ||
286 | if (ret == -ENOENT || ret == -EFBIG) | ||
287 | ret = -ENOENT; | ||
288 | goto fail; | ||
289 | } | ||
290 | |||
291 | ret = btrfs_csum_data(root, data, len, result); | ||
292 | WARN_ON(ret); | ||
293 | if (memcmp(result, &item->csum, BTRFS_CRC32_SIZE)) | ||
294 | ret = 1; | ||
295 | fail: | ||
296 | btrfs_release_path(root, path); | ||
297 | btrfs_free_path(path); | ||
298 | mutex_unlock(&root->fs_info->fs_mutex); | ||
299 | return ret; | ||
300 | } | ||
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 23f029359688..fef7ba1e707f 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -81,6 +81,62 @@ static void btrfs_drop_pages(struct page **pages, size_t num_pages) | |||
81 | } | 81 | } |
82 | } | 82 | } |
83 | 83 | ||
84 | static int insert_inline_extent(struct btrfs_root *root, struct inode *inode, | ||
85 | u64 offset, ssize_t size, | ||
86 | struct buffer_head *bh) | ||
87 | { | ||
88 | struct btrfs_key key; | ||
89 | struct btrfs_path *path; | ||
90 | char *ptr, *kaddr; | ||
91 | struct btrfs_trans_handle *trans; | ||
92 | struct btrfs_file_extent_item *ei; | ||
93 | u32 datasize; | ||
94 | int err = 0; | ||
95 | int ret; | ||
96 | |||
97 | path = btrfs_alloc_path(); | ||
98 | if (!path) | ||
99 | return -ENOMEM; | ||
100 | |||
101 | mutex_lock(&root->fs_info->fs_mutex); | ||
102 | trans = btrfs_start_transaction(root, 1); | ||
103 | btrfs_set_trans_block_group(trans, inode); | ||
104 | |||
105 | key.objectid = inode->i_ino; | ||
106 | key.offset = offset; | ||
107 | key.flags = 0; | ||
108 | btrfs_set_key_type(&key, BTRFS_EXTENT_DATA_KEY); | ||
109 | BUG_ON(size >= PAGE_CACHE_SIZE); | ||
110 | datasize = btrfs_file_extent_calc_inline_size(size); | ||
111 | |||
112 | ret = btrfs_insert_empty_item(trans, root, path, &key, | ||
113 | datasize); | ||
114 | if (ret) { | ||
115 | err = ret; | ||
116 | goto fail; | ||
117 | } | ||
118 | ei = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | ||
119 | path->slots[0], struct btrfs_file_extent_item); | ||
120 | btrfs_set_file_extent_generation(ei, trans->transid); | ||
121 | btrfs_set_file_extent_type(ei, | ||
122 | BTRFS_FILE_EXTENT_INLINE); | ||
123 | ptr = btrfs_file_extent_inline_start(ei); | ||
124 | |||
125 | kaddr = kmap_atomic(bh->b_page, KM_USER0); | ||
126 | btrfs_memcpy(root, path->nodes[0]->b_data, | ||
127 | ptr, kaddr + bh_offset(bh), | ||
128 | size); | ||
129 | kunmap_atomic(kaddr, KM_USER0); | ||
130 | mark_buffer_dirty(path->nodes[0]); | ||
131 | fail: | ||
132 | btrfs_free_path(path); | ||
133 | ret = btrfs_end_transaction(trans, root); | ||
134 | if (ret && !err) | ||
135 | err = ret; | ||
136 | mutex_unlock(&root->fs_info->fs_mutex); | ||
137 | return err; | ||
138 | } | ||
139 | |||
84 | static int dirty_and_release_pages(struct btrfs_trans_handle *trans, | 140 | static int dirty_and_release_pages(struct btrfs_trans_handle *trans, |
85 | struct btrfs_root *root, | 141 | struct btrfs_root *root, |
86 | struct file *file, | 142 | struct file *file, |
@@ -96,57 +152,22 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
96 | int this_write; | 152 | int this_write; |
97 | struct inode *inode = file->f_path.dentry->d_inode; | 153 | struct inode *inode = file->f_path.dentry->d_inode; |
98 | struct buffer_head *bh; | 154 | struct buffer_head *bh; |
99 | struct btrfs_file_extent_item *ei; | ||
100 | 155 | ||
101 | for (i = 0; i < num_pages; i++) { | 156 | for (i = 0; i < num_pages; i++) { |
102 | offset = pos & (PAGE_CACHE_SIZE -1); | 157 | offset = pos & (PAGE_CACHE_SIZE -1); |
103 | this_write = min((size_t)PAGE_CACHE_SIZE - offset, write_bytes); | 158 | this_write = min((size_t)PAGE_CACHE_SIZE - offset, write_bytes); |
104 | /* FIXME, one block at a time */ | ||
105 | 159 | ||
160 | /* FIXME, one block at a time */ | ||
106 | bh = page_buffers(pages[i]); | 161 | bh = page_buffers(pages[i]); |
107 | 162 | ||
108 | if (buffer_mapped(bh) && bh->b_blocknr == 0) { | 163 | if (buffer_mapped(bh) && bh->b_blocknr == 0) { |
109 | struct btrfs_key key; | 164 | ret = insert_inline_extent(root, inode, |
110 | struct btrfs_path *path; | 165 | pages[i]->index << PAGE_CACHE_SHIFT, |
111 | char *ptr, *kaddr; | 166 | offset + this_write, bh); |
112 | u32 datasize; | 167 | if (ret) { |
113 | 168 | err = ret; | |
114 | mutex_lock(&root->fs_info->fs_mutex); | 169 | goto failed; |
115 | trans = btrfs_start_transaction(root, 1); | 170 | } |
116 | btrfs_set_trans_block_group(trans, inode); | ||
117 | |||
118 | /* create an inline extent, and copy the data in */ | ||
119 | path = btrfs_alloc_path(); | ||
120 | BUG_ON(!path); | ||
121 | key.objectid = inode->i_ino; | ||
122 | key.offset = pages[i]->index << PAGE_CACHE_SHIFT; | ||
123 | key.flags = 0; | ||
124 | btrfs_set_key_type(&key, BTRFS_EXTENT_DATA_KEY); | ||
125 | BUG_ON(write_bytes >= PAGE_CACHE_SIZE); | ||
126 | datasize = offset + | ||
127 | btrfs_file_extent_calc_inline_size(write_bytes); | ||
128 | |||
129 | ret = btrfs_insert_empty_item(trans, root, path, &key, | ||
130 | datasize); | ||
131 | BUG_ON(ret); | ||
132 | ei = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | ||
133 | path->slots[0], struct btrfs_file_extent_item); | ||
134 | btrfs_set_file_extent_generation(ei, trans->transid); | ||
135 | btrfs_set_file_extent_type(ei, | ||
136 | BTRFS_FILE_EXTENT_INLINE); | ||
137 | ptr = btrfs_file_extent_inline_start(ei); | ||
138 | |||
139 | kaddr = kmap_atomic(bh->b_page, KM_USER0); | ||
140 | btrfs_memcpy(root, path->nodes[0]->b_data, | ||
141 | ptr, kaddr + bh_offset(bh), | ||
142 | offset + write_bytes); | ||
143 | kunmap_atomic(kaddr, KM_USER0); | ||
144 | |||
145 | mark_buffer_dirty(path->nodes[0]); | ||
146 | btrfs_free_path(path); | ||
147 | ret = btrfs_end_transaction(trans, root); | ||
148 | BUG_ON(ret); | ||
149 | mutex_unlock(&root->fs_info->fs_mutex); | ||
150 | } | 171 | } |
151 | 172 | ||
152 | ret = btrfs_commit_write(file, pages[i], offset, | 173 | ret = btrfs_commit_write(file, pages[i], offset, |
@@ -321,6 +342,7 @@ next_slot: | |||
321 | btrfs_file_extent_disk_blocknr(extent); | 342 | btrfs_file_extent_disk_blocknr(extent); |
322 | } | 343 | } |
323 | ret = btrfs_del_item(trans, root, path); | 344 | ret = btrfs_del_item(trans, root, path); |
345 | /* TODO update progress marker and return */ | ||
324 | BUG_ON(ret); | 346 | BUG_ON(ret); |
325 | btrfs_release_path(root, path); | 347 | btrfs_release_path(root, path); |
326 | extent = NULL; | 348 | extent = NULL; |
@@ -452,7 +474,8 @@ static int prepare_pages(struct btrfs_root *root, | |||
452 | err = btrfs_drop_extents(trans, root, inode, | 474 | err = btrfs_drop_extents(trans, root, inode, |
453 | start_pos, (pos + write_bytes + root->blocksize -1) & | 475 | start_pos, (pos + write_bytes + root->blocksize -1) & |
454 | ~((u64)root->blocksize - 1), &hint_block); | 476 | ~((u64)root->blocksize - 1), &hint_block); |
455 | BUG_ON(err); | 477 | if (err) |
478 | goto failed_release; | ||
456 | } | 479 | } |
457 | 480 | ||
458 | /* insert any holes we need to create */ | 481 | /* insert any holes we need to create */ |
@@ -469,7 +492,8 @@ static int prepare_pages(struct btrfs_root *root, | |||
469 | last_pos_in_file, | 492 | last_pos_in_file, |
470 | 0, 0, hole_size); | 493 | 0, 0, hole_size); |
471 | } | 494 | } |
472 | BUG_ON(err); | 495 | if (err) |
496 | goto failed_release; | ||
473 | } | 497 | } |
474 | 498 | ||
475 | /* | 499 | /* |
@@ -481,11 +505,13 @@ static int prepare_pages(struct btrfs_root *root, | |||
481 | err = btrfs_alloc_extent(trans, root, inode->i_ino, | 505 | err = btrfs_alloc_extent(trans, root, inode->i_ino, |
482 | num_blocks, hint_block, (u64)-1, | 506 | num_blocks, hint_block, (u64)-1, |
483 | &ins, 1); | 507 | &ins, 1); |
484 | BUG_ON(err); | 508 | if (err) |
509 | goto failed_truncate; | ||
485 | err = btrfs_insert_file_extent(trans, root, inode->i_ino, | 510 | err = btrfs_insert_file_extent(trans, root, inode->i_ino, |
486 | start_pos, ins.objectid, ins.offset, | 511 | start_pos, ins.objectid, ins.offset, |
487 | ins.offset); | 512 | ins.offset); |
488 | BUG_ON(err); | 513 | if (err) |
514 | goto failed_truncate; | ||
489 | } else { | 515 | } else { |
490 | ins.offset = 0; | 516 | ins.offset = 0; |
491 | ins.objectid = 0; | 517 | ins.objectid = 0; |
@@ -618,16 +644,21 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
618 | ret = prepare_pages(root, file, pages, num_pages, | 644 | ret = prepare_pages(root, file, pages, num_pages, |
619 | pos, first_index, last_index, | 645 | pos, first_index, last_index, |
620 | write_bytes); | 646 | write_bytes); |
621 | BUG_ON(ret); | 647 | if (ret) |
648 | goto out; | ||
622 | 649 | ||
623 | ret = btrfs_copy_from_user(pos, num_pages, | 650 | ret = btrfs_copy_from_user(pos, num_pages, |
624 | write_bytes, pages, buf); | 651 | write_bytes, pages, buf); |
625 | BUG_ON(ret); | 652 | if (ret) { |
653 | btrfs_drop_pages(pages, num_pages); | ||
654 | goto out; | ||
655 | } | ||
626 | 656 | ||
627 | ret = dirty_and_release_pages(NULL, root, file, pages, | 657 | ret = dirty_and_release_pages(NULL, root, file, pages, |
628 | num_pages, pos, write_bytes); | 658 | num_pages, pos, write_bytes); |
629 | BUG_ON(ret); | ||
630 | btrfs_drop_pages(pages, num_pages); | 659 | btrfs_drop_pages(pages, num_pages); |
660 | if (ret) | ||
661 | goto out; | ||
631 | 662 | ||
632 | buf += write_bytes; | 663 | buf += write_bytes; |
633 | count -= write_bytes; | 664 | count -= write_bytes; |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 94f1c28c25b9..6d031daa7779 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -212,7 +212,11 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans, | |||
212 | struct btrfs_dir_item *di; | 212 | struct btrfs_dir_item *di; |
213 | 213 | ||
214 | path = btrfs_alloc_path(); | 214 | path = btrfs_alloc_path(); |
215 | BUG_ON(!path); | 215 | if (!path) { |
216 | ret = -ENOMEM; | ||
217 | goto err; | ||
218 | } | ||
219 | |||
216 | di = btrfs_lookup_dir_item(trans, root, path, dir->i_ino, | 220 | di = btrfs_lookup_dir_item(trans, root, path, dir->i_ino, |
217 | name, name_len, -1); | 221 | name, name_len, -1); |
218 | if (IS_ERR(di)) { | 222 | if (IS_ERR(di)) { |
@@ -225,7 +229,8 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans, | |||
225 | } | 229 | } |
226 | objectid = btrfs_disk_key_objectid(&di->location); | 230 | objectid = btrfs_disk_key_objectid(&di->location); |
227 | ret = btrfs_delete_one_dir_name(trans, root, path, di); | 231 | ret = btrfs_delete_one_dir_name(trans, root, path, di); |
228 | BUG_ON(ret); | 232 | if (ret) |
233 | goto err; | ||
229 | btrfs_release_path(root, path); | 234 | btrfs_release_path(root, path); |
230 | 235 | ||
231 | di = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino, | 236 | di = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino, |
@@ -239,7 +244,6 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans, | |||
239 | goto err; | 244 | goto err; |
240 | } | 245 | } |
241 | ret = btrfs_delete_one_dir_name(trans, root, path, di); | 246 | ret = btrfs_delete_one_dir_name(trans, root, path, di); |
242 | BUG_ON(ret); | ||
243 | 247 | ||
244 | dentry->d_inode->i_ctime = dir->i_ctime; | 248 | dentry->d_inode->i_ctime = dir->i_ctime; |
245 | err: | 249 | err: |
@@ -248,7 +252,7 @@ err: | |||
248 | dir->i_size -= name_len * 2; | 252 | dir->i_size -= name_len * 2; |
249 | btrfs_update_inode(trans, root, dir); | 253 | btrfs_update_inode(trans, root, dir); |
250 | drop_nlink(dentry->d_inode); | 254 | drop_nlink(dentry->d_inode); |
251 | btrfs_update_inode(trans, root, dentry->d_inode); | 255 | ret = btrfs_update_inode(trans, root, dentry->d_inode); |
252 | dir->i_sb->s_dirt = 1; | 256 | dir->i_sb->s_dirt = 1; |
253 | } | 257 | } |
254 | return ret; | 258 | return ret; |
@@ -359,9 +363,10 @@ static int btrfs_free_inode(struct btrfs_trans_handle *trans, | |||
359 | BUG_ON(!path); | 363 | BUG_ON(!path); |
360 | ret = btrfs_lookup_inode(trans, root, path, | 364 | ret = btrfs_lookup_inode(trans, root, path, |
361 | &BTRFS_I(inode)->location, -1); | 365 | &BTRFS_I(inode)->location, -1); |
362 | BUG_ON(ret); | 366 | if (ret > 0) |
363 | ret = btrfs_del_item(trans, root, path); | 367 | ret = -ENOENT; |
364 | BUG_ON(ret); | 368 | if (!ret) |
369 | ret = btrfs_del_item(trans, root, path); | ||
365 | btrfs_free_path(path); | 370 | btrfs_free_path(path); |
366 | return ret; | 371 | return ret; |
367 | } | 372 | } |
@@ -516,7 +521,8 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | |||
516 | } | 521 | } |
517 | if (del_item) { | 522 | if (del_item) { |
518 | ret = btrfs_del_item(trans, root, path); | 523 | ret = btrfs_del_item(trans, root, path); |
519 | BUG_ON(ret); | 524 | if (ret) |
525 | goto error; | ||
520 | } else { | 526 | } else { |
521 | break; | 527 | break; |
522 | } | 528 | } |
@@ -577,19 +583,22 @@ static int btrfs_truncate_page(struct address_space *mapping, loff_t from) | |||
577 | page->index << PAGE_CACHE_SHIFT, | 583 | page->index << PAGE_CACHE_SHIFT, |
578 | (page->index + 1) << PAGE_CACHE_SHIFT, | 584 | (page->index + 1) << PAGE_CACHE_SHIFT, |
579 | &alloc_hint); | 585 | &alloc_hint); |
580 | BUG_ON(ret); | 586 | if (ret) |
587 | goto out; | ||
581 | ret = btrfs_alloc_extent(trans, root, inode->i_ino, 1, | 588 | ret = btrfs_alloc_extent(trans, root, inode->i_ino, 1, |
582 | alloc_hint, (u64)-1, &ins, 1); | 589 | alloc_hint, (u64)-1, &ins, 1); |
583 | BUG_ON(ret); | 590 | if (ret) |
591 | goto out; | ||
584 | ret = btrfs_insert_file_extent(trans, root, inode->i_ino, | 592 | ret = btrfs_insert_file_extent(trans, root, inode->i_ino, |
585 | page->index << PAGE_CACHE_SHIFT, | 593 | page->index << PAGE_CACHE_SHIFT, |
586 | ins.objectid, 1, 1); | 594 | ins.objectid, 1, 1); |
587 | BUG_ON(ret); | 595 | if (ret) |
596 | goto out; | ||
588 | SetPageChecked(page); | 597 | SetPageChecked(page); |
589 | kaddr = kmap(page); | 598 | kaddr = kmap(page); |
590 | memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset); | 599 | memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset); |
591 | flush_dcache_page(page); | 600 | flush_dcache_page(page); |
592 | btrfs_csum_file_block(trans, root, inode->i_ino, | 601 | ret = btrfs_csum_file_block(trans, root, inode->i_ino, |
593 | page->index << PAGE_CACHE_SHIFT, | 602 | page->index << PAGE_CACHE_SHIFT, |
594 | kaddr, PAGE_CACHE_SIZE); | 603 | kaddr, PAGE_CACHE_SIZE); |
595 | kunmap(page); | 604 | kunmap(page); |
@@ -633,9 +642,10 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
633 | btrfs_set_trans_block_group(trans, inode); | 642 | btrfs_set_trans_block_group(trans, inode); |
634 | err = btrfs_insert_file_extent(trans, root, inode->i_ino, | 643 | err = btrfs_insert_file_extent(trans, root, inode->i_ino, |
635 | pos, 0, 0, hole_size); | 644 | pos, 0, 0, hole_size); |
636 | BUG_ON(err); | ||
637 | btrfs_end_transaction(trans, root); | 645 | btrfs_end_transaction(trans, root); |
638 | mutex_unlock(&root->fs_info->fs_mutex); | 646 | mutex_unlock(&root->fs_info->fs_mutex); |
647 | if (err) | ||
648 | return err; | ||
639 | } | 649 | } |
640 | out: | 650 | out: |
641 | err = inode_setattr(inode, attr); | 651 | err = inode_setattr(inode, attr); |
@@ -657,12 +667,20 @@ void btrfs_delete_inode(struct inode *inode) | |||
657 | trans = btrfs_start_transaction(root, 1); | 667 | trans = btrfs_start_transaction(root, 1); |
658 | btrfs_set_trans_block_group(trans, inode); | 668 | btrfs_set_trans_block_group(trans, inode); |
659 | ret = btrfs_truncate_in_trans(trans, root, inode); | 669 | ret = btrfs_truncate_in_trans(trans, root, inode); |
660 | BUG_ON(ret); | 670 | if (ret) |
661 | btrfs_free_inode(trans, root, inode); | 671 | goto no_delete_lock; |
672 | ret = btrfs_free_inode(trans, root, inode); | ||
673 | if (ret) | ||
674 | goto no_delete_lock; | ||
662 | btrfs_end_transaction(trans, root); | 675 | btrfs_end_transaction(trans, root); |
663 | mutex_unlock(&root->fs_info->fs_mutex); | 676 | mutex_unlock(&root->fs_info->fs_mutex); |
664 | btrfs_btree_balance_dirty(root); | 677 | btrfs_btree_balance_dirty(root); |
665 | return; | 678 | return; |
679 | |||
680 | no_delete_lock: | ||
681 | btrfs_end_transaction(trans, root); | ||
682 | mutex_unlock(&root->fs_info->fs_mutex); | ||
683 | btrfs_btree_balance_dirty(root); | ||
666 | no_delete: | 684 | no_delete: |
667 | clear_inode(inode); | 685 | clear_inode(inode); |
668 | } | 686 | } |
@@ -946,7 +964,7 @@ int btrfs_write_inode(struct inode *inode, int wait) | |||
946 | } | 964 | } |
947 | 965 | ||
948 | /* | 966 | /* |
949 | * This is somewhat expense, updating the tree every time the | 967 | * This is somewhat expensive, updating the tree every time the |
950 | * inode changes. But, it is most likely to find the inode in cache. | 968 | * inode changes. But, it is most likely to find the inode in cache. |
951 | * FIXME, needs more benchmarking...there are no reasons other than performance | 969 | * FIXME, needs more benchmarking...there are no reasons other than performance |
952 | * to keep or drop this code. | 970 | * to keep or drop this code. |
@@ -1002,8 +1020,8 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
1002 | btrfs_set_key_type(location, BTRFS_INODE_ITEM_KEY); | 1020 | btrfs_set_key_type(location, BTRFS_INODE_ITEM_KEY); |
1003 | 1021 | ||
1004 | ret = btrfs_insert_inode(trans, root, objectid, &inode_item); | 1022 | ret = btrfs_insert_inode(trans, root, objectid, &inode_item); |
1005 | BUG_ON(ret); | 1023 | if (ret) |
1006 | 1024 | return ERR_PTR(ret); | |
1007 | insert_inode_hash(inode); | 1025 | insert_inode_hash(inode); |
1008 | return inode; | 1026 | return inode; |
1009 | } | 1027 | } |
@@ -1121,7 +1139,9 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, | |||
1121 | drop_inode = 1; | 1139 | drop_inode = 1; |
1122 | dir->i_sb->s_dirt = 1; | 1140 | dir->i_sb->s_dirt = 1; |
1123 | btrfs_update_inode_block_group(trans, dir); | 1141 | btrfs_update_inode_block_group(trans, dir); |
1124 | btrfs_update_inode(trans, root, inode); | 1142 | err = btrfs_update_inode(trans, root, inode); |
1143 | if (err) | ||
1144 | drop_inode = 1; | ||
1125 | 1145 | ||
1126 | btrfs_end_transaction(trans, root); | 1146 | btrfs_end_transaction(trans, root); |
1127 | mutex_unlock(&root->fs_info->fs_mutex); | 1147 | mutex_unlock(&root->fs_info->fs_mutex); |
@@ -1349,17 +1369,26 @@ not_found: | |||
1349 | ret = btrfs_alloc_extent(trans, root, inode->i_ino, | 1369 | ret = btrfs_alloc_extent(trans, root, inode->i_ino, |
1350 | 1, alloc_hint, (u64)-1, | 1370 | 1, alloc_hint, (u64)-1, |
1351 | &ins, 1); | 1371 | &ins, 1); |
1352 | BUG_ON(ret); | 1372 | if (ret) { |
1373 | err = ret; | ||
1374 | goto out; | ||
1375 | } | ||
1353 | ret = btrfs_insert_file_extent(trans, root, inode->i_ino, | 1376 | ret = btrfs_insert_file_extent(trans, root, inode->i_ino, |
1354 | iblock << inode->i_blkbits, | 1377 | iblock << inode->i_blkbits, |
1355 | ins.objectid, ins.offset, | 1378 | ins.objectid, ins.offset, |
1356 | ins.offset); | 1379 | ins.offset); |
1357 | BUG_ON(ret); | 1380 | if (ret) { |
1381 | err = ret; | ||
1382 | goto out; | ||
1383 | } | ||
1358 | btrfs_map_bh_to_logical(root, result, ins.objectid); | 1384 | btrfs_map_bh_to_logical(root, result, ins.objectid); |
1359 | } | 1385 | } |
1360 | out: | 1386 | out: |
1361 | if (trans) | 1387 | if (trans) { |
1362 | err = btrfs_end_transaction(trans, root); | 1388 | ret = btrfs_end_transaction(trans, root); |
1389 | if (!err) | ||
1390 | err = ret; | ||
1391 | } | ||
1363 | btrfs_free_path(path); | 1392 | btrfs_free_path(path); |
1364 | return err; | 1393 | return err; |
1365 | } | 1394 | } |
@@ -1375,8 +1404,8 @@ int btrfs_get_block(struct inode *inode, sector_t iblock, | |||
1375 | return err; | 1404 | return err; |
1376 | } | 1405 | } |
1377 | 1406 | ||
1378 | int btrfs_get_block_csum(struct inode *inode, sector_t iblock, | 1407 | static int btrfs_get_block_csum(struct inode *inode, sector_t iblock, |
1379 | struct buffer_head *result, int create) | 1408 | struct buffer_head *result, int create) |
1380 | { | 1409 | { |
1381 | int ret; | 1410 | int ret; |
1382 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1411 | struct btrfs_root *root = BTRFS_I(inode)->root; |
@@ -1397,7 +1426,7 @@ int btrfs_get_block_csum(struct inode *inode, sector_t iblock, | |||
1397 | /* a csum that isn't present is a preallocated region. */ | 1426 | /* a csum that isn't present is a preallocated region. */ |
1398 | if (ret == -ENOENT || ret == -EFBIG) | 1427 | if (ret == -ENOENT || ret == -EFBIG) |
1399 | ret = 0; | 1428 | ret = 0; |
1400 | result->b_private = 0; | 1429 | result->b_private = NULL; |
1401 | goto out; | 1430 | goto out; |
1402 | } | 1431 | } |
1403 | memcpy((char *)&result->b_private, &item->csum, BTRFS_CRC32_SIZE); | 1432 | memcpy((char *)&result->b_private, &item->csum, BTRFS_CRC32_SIZE); |
@@ -1736,11 +1765,10 @@ static int __btrfs_write_full_page(struct inode *inode, struct page *page, | |||
1736 | trans = btrfs_start_transaction(root, 1); | 1765 | trans = btrfs_start_transaction(root, 1); |
1737 | btrfs_set_trans_block_group(trans, inode); | 1766 | btrfs_set_trans_block_group(trans, inode); |
1738 | kaddr = kmap(page); | 1767 | kaddr = kmap(page); |
1739 | ret = btrfs_csum_file_block(trans, root, inode->i_ino, | 1768 | btrfs_csum_file_block(trans, root, inode->i_ino, |
1740 | off, kaddr + bh_offset(bh), | 1769 | off, kaddr + bh_offset(bh), |
1741 | bh->b_size); | 1770 | bh->b_size); |
1742 | kunmap(page); | 1771 | kunmap(page); |
1743 | BUG_ON(ret); | ||
1744 | ret = btrfs_end_transaction(trans, root); | 1772 | ret = btrfs_end_transaction(trans, root); |
1745 | BUG_ON(ret); | 1773 | BUG_ON(ret); |
1746 | mutex_unlock(&root->fs_info->fs_mutex); | 1774 | mutex_unlock(&root->fs_info->fs_mutex); |
@@ -1930,7 +1958,6 @@ static void btrfs_truncate(struct inode *inode) | |||
1930 | 1958 | ||
1931 | /* FIXME, add redo link to tree so we don't leak on crash */ | 1959 | /* FIXME, add redo link to tree so we don't leak on crash */ |
1932 | ret = btrfs_truncate_in_trans(trans, root, inode); | 1960 | ret = btrfs_truncate_in_trans(trans, root, inode); |
1933 | BUG_ON(ret); | ||
1934 | btrfs_update_inode(trans, root, inode); | 1961 | btrfs_update_inode(trans, root, inode); |
1935 | ret = btrfs_end_transaction(trans, root); | 1962 | ret = btrfs_end_transaction(trans, root); |
1936 | BUG_ON(ret); | 1963 | BUG_ON(ret); |
@@ -1970,6 +1997,7 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen) | |||
1970 | struct inode *inode; | 1997 | struct inode *inode; |
1971 | struct inode *dir; | 1998 | struct inode *dir; |
1972 | int ret; | 1999 | int ret; |
2000 | int err; | ||
1973 | u64 objectid; | 2001 | u64 objectid; |
1974 | u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID; | 2002 | u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID; |
1975 | 2003 | ||
@@ -1978,8 +2006,8 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen) | |||
1978 | BUG_ON(!trans); | 2006 | BUG_ON(!trans); |
1979 | 2007 | ||
1980 | subvol = btrfs_alloc_free_block(trans, root, 0); | 2008 | subvol = btrfs_alloc_free_block(trans, root, 0); |
1981 | if (subvol == NULL) | 2009 | if (IS_ERR(subvol)) |
1982 | return -ENOSPC; | 2010 | return PTR_ERR(subvol); |
1983 | leaf = btrfs_buffer_leaf(subvol); | 2011 | leaf = btrfs_buffer_leaf(subvol); |
1984 | btrfs_set_header_nritems(&leaf->header, 0); | 2012 | btrfs_set_header_nritems(&leaf->header, 0); |
1985 | btrfs_set_header_level(&leaf->header, 0); | 2013 | btrfs_set_header_level(&leaf->header, 0); |
@@ -2005,7 +2033,8 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen) | |||
2005 | 2033 | ||
2006 | ret = btrfs_find_free_objectid(trans, root->fs_info->tree_root, | 2034 | ret = btrfs_find_free_objectid(trans, root->fs_info->tree_root, |
2007 | 0, &objectid); | 2035 | 0, &objectid); |
2008 | BUG_ON(ret); | 2036 | if (ret) |
2037 | goto fail; | ||
2009 | 2038 | ||
2010 | btrfs_set_root_dirid(&root_item, new_dirid); | 2039 | btrfs_set_root_dirid(&root_item, new_dirid); |
2011 | 2040 | ||
@@ -2015,7 +2044,8 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen) | |||
2015 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); | 2044 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); |
2016 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, | 2045 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, |
2017 | &root_item); | 2046 | &root_item); |
2018 | BUG_ON(ret); | 2047 | if (ret) |
2048 | goto fail; | ||
2019 | 2049 | ||
2020 | /* | 2050 | /* |
2021 | * insert the directory item | 2051 | * insert the directory item |
@@ -2025,10 +2055,12 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen) | |||
2025 | ret = btrfs_insert_dir_item(trans, root->fs_info->tree_root, | 2055 | ret = btrfs_insert_dir_item(trans, root->fs_info->tree_root, |
2026 | name, namelen, dir->i_ino, &key, | 2056 | name, namelen, dir->i_ino, &key, |
2027 | BTRFS_FT_DIR); | 2057 | BTRFS_FT_DIR); |
2028 | BUG_ON(ret); | 2058 | if (ret) |
2059 | goto fail; | ||
2029 | 2060 | ||
2030 | ret = btrfs_commit_transaction(trans, root); | 2061 | ret = btrfs_commit_transaction(trans, root); |
2031 | BUG_ON(ret); | 2062 | if (ret) |
2063 | goto fail_commit; | ||
2032 | 2064 | ||
2033 | new_root = btrfs_read_fs_root(root->fs_info, &key); | 2065 | new_root = btrfs_read_fs_root(root->fs_info, &key); |
2034 | BUG_ON(!new_root); | 2066 | BUG_ON(!new_root); |
@@ -2038,24 +2070,29 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen) | |||
2038 | 2070 | ||
2039 | inode = btrfs_new_inode(trans, new_root, new_dirid, | 2071 | inode = btrfs_new_inode(trans, new_root, new_dirid, |
2040 | BTRFS_I(dir)->block_group, S_IFDIR | 0700); | 2072 | BTRFS_I(dir)->block_group, S_IFDIR | 0700); |
2073 | if (IS_ERR(inode)) | ||
2074 | goto fail; | ||
2041 | inode->i_op = &btrfs_dir_inode_operations; | 2075 | inode->i_op = &btrfs_dir_inode_operations; |
2042 | inode->i_fop = &btrfs_dir_file_operations; | 2076 | inode->i_fop = &btrfs_dir_file_operations; |
2043 | new_root->inode = inode; | 2077 | new_root->inode = inode; |
2044 | 2078 | ||
2045 | ret = btrfs_make_empty_dir(trans, new_root, new_dirid, new_dirid); | 2079 | ret = btrfs_make_empty_dir(trans, new_root, new_dirid, new_dirid); |
2046 | BUG_ON(ret); | 2080 | if (ret) |
2081 | goto fail; | ||
2047 | 2082 | ||
2048 | inode->i_nlink = 1; | 2083 | inode->i_nlink = 1; |
2049 | inode->i_size = 6; | 2084 | inode->i_size = 6; |
2050 | ret = btrfs_update_inode(trans, new_root, inode); | 2085 | ret = btrfs_update_inode(trans, new_root, inode); |
2051 | BUG_ON(ret); | 2086 | if (ret) |
2052 | 2087 | goto fail; | |
2053 | ret = btrfs_commit_transaction(trans, new_root); | 2088 | fail: |
2054 | BUG_ON(ret); | 2089 | err = btrfs_commit_transaction(trans, root); |
2055 | 2090 | if (err && !ret) | |
2091 | ret = err; | ||
2092 | fail_commit: | ||
2056 | mutex_unlock(&root->fs_info->fs_mutex); | 2093 | mutex_unlock(&root->fs_info->fs_mutex); |
2057 | btrfs_btree_balance_dirty(root); | 2094 | btrfs_btree_balance_dirty(root); |
2058 | return 0; | 2095 | return ret; |
2059 | } | 2096 | } |
2060 | 2097 | ||
2061 | static int create_snapshot(struct btrfs_root *root, char *name, int namelen) | 2098 | static int create_snapshot(struct btrfs_root *root, char *name, int namelen) |
@@ -2064,6 +2101,7 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen) | |||
2064 | struct btrfs_key key; | 2101 | struct btrfs_key key; |
2065 | struct btrfs_root_item new_root_item; | 2102 | struct btrfs_root_item new_root_item; |
2066 | int ret; | 2103 | int ret; |
2104 | int err; | ||
2067 | u64 objectid; | 2105 | u64 objectid; |
2068 | 2106 | ||
2069 | if (!root->ref_cows) | 2107 | if (!root->ref_cows) |
@@ -2074,11 +2112,13 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen) | |||
2074 | BUG_ON(!trans); | 2112 | BUG_ON(!trans); |
2075 | 2113 | ||
2076 | ret = btrfs_update_inode(trans, root, root->inode); | 2114 | ret = btrfs_update_inode(trans, root, root->inode); |
2077 | BUG_ON(ret); | 2115 | if (ret) |
2116 | goto fail; | ||
2078 | 2117 | ||
2079 | ret = btrfs_find_free_objectid(trans, root->fs_info->tree_root, | 2118 | ret = btrfs_find_free_objectid(trans, root->fs_info->tree_root, |
2080 | 0, &objectid); | 2119 | 0, &objectid); |
2081 | BUG_ON(ret); | 2120 | if (ret) |
2121 | goto fail; | ||
2082 | 2122 | ||
2083 | memcpy(&new_root_item, &root->root_item, | 2123 | memcpy(&new_root_item, &root->root_item, |
2084 | sizeof(new_root_item)); | 2124 | sizeof(new_root_item)); |
@@ -2091,7 +2131,8 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen) | |||
2091 | 2131 | ||
2092 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, | 2132 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, |
2093 | &new_root_item); | 2133 | &new_root_item); |
2094 | BUG_ON(ret); | 2134 | if (ret) |
2135 | goto fail; | ||
2095 | 2136 | ||
2096 | /* | 2137 | /* |
2097 | * insert the directory item | 2138 | * insert the directory item |
@@ -2102,16 +2143,20 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen) | |||
2102 | root->fs_info->sb->s_root->d_inode->i_ino, | 2143 | root->fs_info->sb->s_root->d_inode->i_ino, |
2103 | &key, BTRFS_FT_DIR); | 2144 | &key, BTRFS_FT_DIR); |
2104 | 2145 | ||
2105 | BUG_ON(ret); | 2146 | if (ret) |
2147 | goto fail; | ||
2106 | 2148 | ||
2107 | ret = btrfs_inc_root_ref(trans, root); | 2149 | ret = btrfs_inc_root_ref(trans, root); |
2108 | BUG_ON(ret); | 2150 | if (ret) |
2151 | goto fail; | ||
2109 | 2152 | ||
2110 | ret = btrfs_commit_transaction(trans, root); | 2153 | fail: |
2111 | BUG_ON(ret); | 2154 | err = btrfs_commit_transaction(trans, root); |
2155 | if (err && !ret) | ||
2156 | ret = err; | ||
2112 | mutex_unlock(&root->fs_info->fs_mutex); | 2157 | mutex_unlock(&root->fs_info->fs_mutex); |
2113 | btrfs_btree_balance_dirty(root); | 2158 | btrfs_btree_balance_dirty(root); |
2114 | return 0; | 2159 | return ret; |
2115 | } | 2160 | } |
2116 | 2161 | ||
2117 | int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int | 2162 | int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int |
@@ -2148,12 +2193,13 @@ int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int | |||
2148 | btrfs_free_path(path); | 2193 | btrfs_free_path(path); |
2149 | if (di && !IS_ERR(di)) | 2194 | if (di && !IS_ERR(di)) |
2150 | return -EEXIST; | 2195 | return -EEXIST; |
2196 | if (IS_ERR(di)) | ||
2197 | return PTR_ERR(di); | ||
2151 | 2198 | ||
2152 | if (root == root->fs_info->tree_root) | 2199 | if (root == root->fs_info->tree_root) |
2153 | ret = create_subvol(root, vol_args.name, namelen); | 2200 | ret = create_subvol(root, vol_args.name, namelen); |
2154 | else | 2201 | else |
2155 | ret = create_snapshot(root, vol_args.name, namelen); | 2202 | ret = create_snapshot(root, vol_args.name, namelen); |
2156 | WARN_ON(ret); | ||
2157 | break; | 2203 | break; |
2158 | default: | 2204 | default: |
2159 | return -ENOTTY; | 2205 | return -ENOTTY; |
@@ -2316,7 +2362,6 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry, | |||
2316 | old_parent_oid = btrfs_disk_key_objectid(&di->location); | 2362 | old_parent_oid = btrfs_disk_key_objectid(&di->location); |
2317 | ret = btrfs_del_item(trans, root, path); | 2363 | ret = btrfs_del_item(trans, root, path); |
2318 | if (ret) { | 2364 | if (ret) { |
2319 | ret = -EIO; | ||
2320 | goto out_fail; | 2365 | goto out_fail; |
2321 | } | 2366 | } |
2322 | btrfs_release_path(root, path); | 2367 | btrfs_release_path(root, path); |
@@ -2335,7 +2380,6 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry, | |||
2335 | } | 2380 | } |
2336 | ret = btrfs_del_item(trans, root, path); | 2381 | ret = btrfs_del_item(trans, root, path); |
2337 | if (ret) { | 2382 | if (ret) { |
2338 | ret = -EIO; | ||
2339 | goto out_fail; | 2383 | goto out_fail; |
2340 | } | 2384 | } |
2341 | btrfs_release_path(root, path); | 2385 | btrfs_release_path(root, path); |
@@ -2361,7 +2405,9 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry, | |||
2361 | clear_nlink(new_inode); | 2405 | clear_nlink(new_inode); |
2362 | else | 2406 | else |
2363 | drop_nlink(new_inode); | 2407 | drop_nlink(new_inode); |
2364 | btrfs_update_inode(trans, root, new_inode); | 2408 | ret = btrfs_update_inode(trans, root, new_inode); |
2409 | if (ret) | ||
2410 | goto out_fail; | ||
2365 | } | 2411 | } |
2366 | ret = btrfs_add_link(trans, new_dentry, old_inode); | 2412 | ret = btrfs_add_link(trans, new_dentry, old_inode); |
2367 | if (ret) | 2413 | if (ret) |
@@ -2433,7 +2479,10 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, | |||
2433 | datasize = btrfs_file_extent_calc_inline_size(name_len); | 2479 | datasize = btrfs_file_extent_calc_inline_size(name_len); |
2434 | err = btrfs_insert_empty_item(trans, root, path, &key, | 2480 | err = btrfs_insert_empty_item(trans, root, path, &key, |
2435 | datasize); | 2481 | datasize); |
2436 | BUG_ON(err); | 2482 | if (err) { |
2483 | drop_inode = 1; | ||
2484 | goto out_unlock; | ||
2485 | } | ||
2437 | ei = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | 2486 | ei = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), |
2438 | path->slots[0], struct btrfs_file_extent_item); | 2487 | path->slots[0], struct btrfs_file_extent_item); |
2439 | btrfs_set_file_extent_generation(ei, trans->transid); | 2488 | btrfs_set_file_extent_generation(ei, trans->transid); |
@@ -2447,13 +2496,13 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, | |||
2447 | inode->i_op = &btrfs_symlink_inode_operations; | 2496 | inode->i_op = &btrfs_symlink_inode_operations; |
2448 | inode->i_mapping->a_ops = &btrfs_symlink_aops; | 2497 | inode->i_mapping->a_ops = &btrfs_symlink_aops; |
2449 | inode->i_size = name_len - 1; | 2498 | inode->i_size = name_len - 1; |
2450 | btrfs_update_inode(trans, root, inode); | 2499 | err = btrfs_update_inode(trans, root, inode); |
2451 | err = 0; | 2500 | if (err) |
2501 | drop_inode = 1; | ||
2452 | 2502 | ||
2453 | out_unlock: | 2503 | out_unlock: |
2454 | btrfs_end_transaction(trans, root); | 2504 | btrfs_end_transaction(trans, root); |
2455 | mutex_unlock(&root->fs_info->fs_mutex); | 2505 | mutex_unlock(&root->fs_info->fs_mutex); |
2456 | |||
2457 | if (drop_inode) { | 2506 | if (drop_inode) { |
2458 | inode_dec_link_count(inode); | 2507 | inode_dec_link_count(inode); |
2459 | iput(inode); | 2508 | iput(inode); |
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index 8e1b9046d5ec..ac0fae7780ff 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c | |||
@@ -90,7 +90,6 @@ int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root | |||
90 | { | 90 | { |
91 | int ret; | 91 | int ret; |
92 | ret = btrfs_insert_item(trans, root, key, item, sizeof(*item)); | 92 | ret = btrfs_insert_item(trans, root, key, item, sizeof(*item)); |
93 | BUG_ON(ret); | ||
94 | return ret; | 93 | return ret; |
95 | } | 94 | } |
96 | 95 | ||
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index ef8ad18b275c..c11ecf500202 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -125,9 +125,8 @@ static int btrfs_sync_fs(struct super_block *sb, int wait) | |||
125 | trans = btrfs_start_transaction(root, 1); | 125 | trans = btrfs_start_transaction(root, 1); |
126 | ret = btrfs_commit_transaction(trans, root); | 126 | ret = btrfs_commit_transaction(trans, root); |
127 | sb->s_dirt = 0; | 127 | sb->s_dirt = 0; |
128 | BUG_ON(ret); | ||
129 | mutex_unlock(&root->fs_info->fs_mutex); | 128 | mutex_unlock(&root->fs_info->fs_mutex); |
130 | return 0; | 129 | return ret; |
131 | } | 130 | } |
132 | 131 | ||
133 | static void btrfs_write_super(struct super_block *sb) | 132 | static void btrfs_write_super(struct super_block *sb) |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index b5b99a85763f..321f8852755b 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -219,7 +219,8 @@ static int add_dirty_roots(struct btrfs_trans_handle *trans, | |||
219 | struct btrfs_root *root; | 219 | struct btrfs_root *root; |
220 | int i; | 220 | int i; |
221 | int ret; | 221 | int ret; |
222 | int err; | 222 | int err = 0; |
223 | |||
223 | while(1) { | 224 | while(1) { |
224 | ret = radix_tree_gang_lookup_tag(radix, (void **)gang, 0, | 225 | ret = radix_tree_gang_lookup_tag(radix, (void **)gang, 0, |
225 | ARRAY_SIZE(gang), | 226 | ARRAY_SIZE(gang), |
@@ -251,11 +252,12 @@ static int add_dirty_roots(struct btrfs_trans_handle *trans, | |||
251 | err = btrfs_insert_root(trans, root->fs_info->tree_root, | 252 | err = btrfs_insert_root(trans, root->fs_info->tree_root, |
252 | &root->root_key, | 253 | &root->root_key, |
253 | &root->root_item); | 254 | &root->root_item); |
254 | BUG_ON(err); | 255 | if (err) |
256 | break; | ||
255 | list_add(&dirty->list, list); | 257 | list_add(&dirty->list, list); |
256 | } | 258 | } |
257 | } | 259 | } |
258 | return 0; | 260 | return err; |
259 | } | 261 | } |
260 | 262 | ||
261 | static int drop_dirty_roots(struct btrfs_root *tree_root, | 263 | static int drop_dirty_roots(struct btrfs_root *tree_root, |
@@ -263,7 +265,7 @@ static int drop_dirty_roots(struct btrfs_root *tree_root, | |||
263 | { | 265 | { |
264 | struct dirty_root *dirty; | 266 | struct dirty_root *dirty; |
265 | struct btrfs_trans_handle *trans; | 267 | struct btrfs_trans_handle *trans; |
266 | int ret; | 268 | int ret = 0; |
267 | while(!list_empty(list)) { | 269 | while(!list_empty(list)) { |
268 | mutex_lock(&tree_root->fs_info->fs_mutex); | 270 | mutex_lock(&tree_root->fs_info->fs_mutex); |
269 | dirty = list_entry(list->next, struct dirty_root, list); | 271 | dirty = list_entry(list->next, struct dirty_root, list); |
@@ -274,14 +276,15 @@ static int drop_dirty_roots(struct btrfs_root *tree_root, | |||
274 | BUG_ON(ret); | 276 | BUG_ON(ret); |
275 | 277 | ||
276 | ret = btrfs_del_root(trans, tree_root, &dirty->snap_key); | 278 | ret = btrfs_del_root(trans, tree_root, &dirty->snap_key); |
277 | BUG_ON(ret); | 279 | if (ret) |
280 | break; | ||
278 | ret = btrfs_end_transaction(trans, tree_root); | 281 | ret = btrfs_end_transaction(trans, tree_root); |
279 | BUG_ON(ret); | 282 | BUG_ON(ret); |
280 | kfree(dirty); | 283 | kfree(dirty); |
281 | mutex_unlock(&tree_root->fs_info->fs_mutex); | 284 | mutex_unlock(&tree_root->fs_info->fs_mutex); |
282 | btrfs_btree_balance_dirty(tree_root); | 285 | btrfs_btree_balance_dirty(tree_root); |
283 | } | 286 | } |
284 | return 0; | 287 | return ret; |
285 | } | 288 | } |
286 | 289 | ||
287 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | 290 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, |
@@ -321,9 +324,13 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
321 | } | 324 | } |
322 | finish_wait(&trans->transaction->writer_wait, &wait); | 325 | finish_wait(&trans->transaction->writer_wait, &wait); |
323 | WARN_ON(cur_trans != trans->transaction); | 326 | WARN_ON(cur_trans != trans->transaction); |
324 | add_dirty_roots(trans, &root->fs_info->fs_roots_radix, &dirty_fs_roots); | 327 | ret = add_dirty_roots(trans, &root->fs_info->fs_roots_radix, |
328 | &dirty_fs_roots); | ||
329 | BUG_ON(ret); | ||
330 | |||
325 | ret = btrfs_commit_tree_roots(trans, root); | 331 | ret = btrfs_commit_tree_roots(trans, root); |
326 | BUG_ON(ret); | 332 | BUG_ON(ret); |
333 | |||
327 | cur_trans = root->fs_info->running_transaction; | 334 | cur_trans = root->fs_info->running_transaction; |
328 | root->fs_info->running_transaction = NULL; | 335 | root->fs_info->running_transaction = NULL; |
329 | if (cur_trans->list.prev != &root->fs_info->trans_list) { | 336 | if (cur_trans->list.prev != &root->fs_info->trans_list) { |