diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-12-11 09:25:06 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:58 -0400 |
commit | 7bb86316c3961d1bc401ef184fd996f999556c7f (patch) | |
tree | e67de3b594cf680f295010095a71ed7e825cb757 /fs/btrfs | |
parent | 74493f7a59bfd4d1c7029c74ab2cd0e400612c6b (diff) |
Btrfs: Add back pointers from extents to the btree or file referencing them
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/ctree.c | 196 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 41 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 2 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 373 | ||||
-rw-r--r-- | fs/btrfs/file.c | 20 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 38 | ||||
-rw-r--r-- | fs/btrfs/print-tree.c | 10 | ||||
-rw-r--r-- | fs/btrfs/tree-defrag.c | 2 |
8 files changed, 577 insertions, 105 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 5697705f7530..fd8233e05cf4 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -77,13 +77,37 @@ static int __btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
77 | struct extent_buffer **cow_ret, | 77 | struct extent_buffer **cow_ret, |
78 | u64 search_start, u64 empty_size) | 78 | u64 search_start, u64 empty_size) |
79 | { | 79 | { |
80 | u64 root_gen; | ||
80 | struct extent_buffer *cow; | 81 | struct extent_buffer *cow; |
82 | u32 nritems; | ||
81 | int ret = 0; | 83 | int ret = 0; |
82 | int different_trans = 0; | 84 | int different_trans = 0; |
85 | int level; | ||
86 | struct btrfs_key first_key; | ||
87 | |||
88 | if (root->ref_cows) { | ||
89 | root_gen = trans->transid; | ||
90 | } else { | ||
91 | root_gen = 0; | ||
92 | } | ||
83 | 93 | ||
94 | WARN_ON(root->ref_cows && trans->transid != | ||
95 | root->fs_info->running_transaction->transid); | ||
84 | WARN_ON(root->ref_cows && trans->transid != root->last_trans); | 96 | WARN_ON(root->ref_cows && trans->transid != root->last_trans); |
85 | 97 | ||
86 | cow = btrfs_alloc_free_block(trans, root, buf->len, | 98 | level = btrfs_header_level(buf); |
99 | nritems = btrfs_header_nritems(buf); | ||
100 | if (nritems) { | ||
101 | if (level == 0) | ||
102 | btrfs_item_key_to_cpu(buf, &first_key, 0); | ||
103 | else | ||
104 | btrfs_node_key_to_cpu(buf, &first_key, 0); | ||
105 | } else { | ||
106 | first_key.objectid = 0; | ||
107 | } | ||
108 | cow = __btrfs_alloc_free_block(trans, root, buf->len, | ||
109 | root->root_key.objectid, | ||
110 | root_gen, first_key.objectid, level, | ||
87 | search_start, empty_size); | 111 | search_start, empty_size); |
88 | if (IS_ERR(cow)) | 112 | if (IS_ERR(cow)) |
89 | return PTR_ERR(cow); | 113 | return PTR_ERR(cow); |
@@ -104,14 +128,17 @@ static int __btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
104 | } | 128 | } |
105 | 129 | ||
106 | if (buf == root->node) { | 130 | if (buf == root->node) { |
131 | root_gen = btrfs_header_generation(buf); | ||
107 | root->node = cow; | 132 | root->node = cow; |
108 | extent_buffer_get(cow); | 133 | extent_buffer_get(cow); |
109 | if (buf != root->commit_root) { | 134 | if (buf != root->commit_root) { |
110 | btrfs_free_extent(trans, root, buf->start, | 135 | btrfs_free_extent(trans, root, buf->start, |
111 | buf->len, 1); | 136 | buf->len, root->root_key.objectid, |
137 | root_gen, 0, 0, 1); | ||
112 | } | 138 | } |
113 | free_extent_buffer(buf); | 139 | free_extent_buffer(buf); |
114 | } else { | 140 | } else { |
141 | root_gen = btrfs_header_generation(parent); | ||
115 | btrfs_set_node_blockptr(parent, parent_slot, | 142 | btrfs_set_node_blockptr(parent, parent_slot, |
116 | cow->start); | 143 | cow->start); |
117 | WARN_ON(trans->transid == 0); | 144 | WARN_ON(trans->transid == 0); |
@@ -119,7 +146,9 @@ static int __btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
119 | trans->transid); | 146 | trans->transid); |
120 | btrfs_mark_buffer_dirty(parent); | 147 | btrfs_mark_buffer_dirty(parent); |
121 | WARN_ON(btrfs_header_generation(parent) != trans->transid); | 148 | WARN_ON(btrfs_header_generation(parent) != trans->transid); |
122 | btrfs_free_extent(trans, root, buf->start, buf->len, 1); | 149 | btrfs_free_extent(trans, root, buf->start, buf->len, |
150 | btrfs_header_owner(parent), root_gen, | ||
151 | 0, 0, 1); | ||
123 | } | 152 | } |
124 | free_extent_buffer(buf); | 153 | free_extent_buffer(buf); |
125 | btrfs_mark_buffer_dirty(cow); | 154 | btrfs_mark_buffer_dirty(cow); |
@@ -606,6 +635,8 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
606 | return 0; | 635 | return 0; |
607 | 636 | ||
608 | mid = path->nodes[level]; | 637 | mid = path->nodes[level]; |
638 | WARN_ON(btrfs_header_generation(mid) != trans->transid); | ||
639 | |||
609 | orig_ptr = btrfs_node_blockptr(mid, orig_slot); | 640 | orig_ptr = btrfs_node_blockptr(mid, orig_slot); |
610 | 641 | ||
611 | if (level < BTRFS_MAX_LEVEL - 1) | 642 | if (level < BTRFS_MAX_LEVEL - 1) |
@@ -631,7 +662,9 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
631 | wait_on_tree_block_writeback(root, mid); | 662 | wait_on_tree_block_writeback(root, mid); |
632 | /* once for the path */ | 663 | /* once for the path */ |
633 | free_extent_buffer(mid); | 664 | free_extent_buffer(mid); |
634 | ret = btrfs_free_extent(trans, root, mid->start, mid->len, 1); | 665 | ret = btrfs_free_extent(trans, root, mid->start, mid->len, |
666 | root->root_key.objectid, | ||
667 | btrfs_header_generation(mid), 0, 0, 1); | ||
635 | /* once for the root ptr */ | 668 | /* once for the root ptr */ |
636 | free_extent_buffer(mid); | 669 | free_extent_buffer(mid); |
637 | return ret; | 670 | return ret; |
@@ -681,6 +714,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
681 | ret = wret; | 714 | ret = wret; |
682 | if (btrfs_header_nritems(right) == 0) { | 715 | if (btrfs_header_nritems(right) == 0) { |
683 | u64 bytenr = right->start; | 716 | u64 bytenr = right->start; |
717 | u64 generation = btrfs_header_generation(parent); | ||
684 | u32 blocksize = right->len; | 718 | u32 blocksize = right->len; |
685 | 719 | ||
686 | clean_tree_block(trans, root, right); | 720 | clean_tree_block(trans, root, right); |
@@ -692,7 +726,9 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
692 | if (wret) | 726 | if (wret) |
693 | ret = wret; | 727 | ret = wret; |
694 | wret = btrfs_free_extent(trans, root, bytenr, | 728 | wret = btrfs_free_extent(trans, root, bytenr, |
695 | blocksize, 1); | 729 | blocksize, |
730 | btrfs_header_owner(parent), | ||
731 | generation, 0, 0, 1); | ||
696 | if (wret) | 732 | if (wret) |
697 | ret = wret; | 733 | ret = wret; |
698 | } else { | 734 | } else { |
@@ -722,6 +758,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
722 | } | 758 | } |
723 | if (btrfs_header_nritems(mid) == 0) { | 759 | if (btrfs_header_nritems(mid) == 0) { |
724 | /* we've managed to empty the middle node, drop it */ | 760 | /* we've managed to empty the middle node, drop it */ |
761 | u64 root_gen = btrfs_header_generation(parent); | ||
725 | u64 bytenr = mid->start; | 762 | u64 bytenr = mid->start; |
726 | u32 blocksize = mid->len; | 763 | u32 blocksize = mid->len; |
727 | clean_tree_block(trans, root, mid); | 764 | clean_tree_block(trans, root, mid); |
@@ -731,7 +768,9 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
731 | wret = del_ptr(trans, root, path, level + 1, pslot); | 768 | wret = del_ptr(trans, root, path, level + 1, pslot); |
732 | if (wret) | 769 | if (wret) |
733 | ret = wret; | 770 | ret = wret; |
734 | wret = btrfs_free_extent(trans, root, bytenr, blocksize, 1); | 771 | wret = btrfs_free_extent(trans, root, bytenr, blocksize, |
772 | btrfs_header_owner(parent), | ||
773 | root_gen, 0, 0, 1); | ||
735 | if (wret) | 774 | if (wret) |
736 | ret = wret; | 775 | ret = wret; |
737 | } else { | 776 | } else { |
@@ -788,6 +827,7 @@ static int push_nodes_for_insert(struct btrfs_trans_handle *trans, | |||
788 | return 1; | 827 | return 1; |
789 | 828 | ||
790 | mid = path->nodes[level]; | 829 | mid = path->nodes[level]; |
830 | WARN_ON(btrfs_header_generation(mid) != trans->transid); | ||
791 | orig_ptr = btrfs_node_blockptr(mid, orig_slot); | 831 | orig_ptr = btrfs_node_blockptr(mid, orig_slot); |
792 | 832 | ||
793 | if (level < BTRFS_MAX_LEVEL - 1) | 833 | if (level < BTRFS_MAX_LEVEL - 1) |
@@ -1113,6 +1153,8 @@ static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1113 | src_nritems = btrfs_header_nritems(src); | 1153 | src_nritems = btrfs_header_nritems(src); |
1114 | dst_nritems = btrfs_header_nritems(dst); | 1154 | dst_nritems = btrfs_header_nritems(dst); |
1115 | push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems; | 1155 | push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems; |
1156 | WARN_ON(btrfs_header_generation(src) != trans->transid); | ||
1157 | WARN_ON(btrfs_header_generation(dst) != trans->transid); | ||
1116 | 1158 | ||
1117 | if (push_items <= 0) { | 1159 | if (push_items <= 0) { |
1118 | return 1; | 1160 | return 1; |
@@ -1159,6 +1201,9 @@ static int balance_node_right(struct btrfs_trans_handle *trans, | |||
1159 | int dst_nritems; | 1201 | int dst_nritems; |
1160 | int ret = 0; | 1202 | int ret = 0; |
1161 | 1203 | ||
1204 | WARN_ON(btrfs_header_generation(src) != trans->transid); | ||
1205 | WARN_ON(btrfs_header_generation(dst) != trans->transid); | ||
1206 | |||
1162 | src_nritems = btrfs_header_nritems(src); | 1207 | src_nritems = btrfs_header_nritems(src); |
1163 | dst_nritems = btrfs_header_nritems(dst); | 1208 | dst_nritems = btrfs_header_nritems(dst); |
1164 | push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems; | 1209 | push_items = BTRFS_NODEPTRS_PER_BLOCK(root) - dst_nritems; |
@@ -1202,6 +1247,8 @@ static int insert_new_root(struct btrfs_trans_handle *trans, | |||
1202 | struct btrfs_root *root, | 1247 | struct btrfs_root *root, |
1203 | struct btrfs_path *path, int level) | 1248 | struct btrfs_path *path, int level) |
1204 | { | 1249 | { |
1250 | u64 root_gen; | ||
1251 | u64 lower_gen; | ||
1205 | struct extent_buffer *lower; | 1252 | struct extent_buffer *lower; |
1206 | struct extent_buffer *c; | 1253 | struct extent_buffer *c; |
1207 | struct btrfs_disk_key lower_key; | 1254 | struct btrfs_disk_key lower_key; |
@@ -1209,7 +1256,20 @@ static int insert_new_root(struct btrfs_trans_handle *trans, | |||
1209 | BUG_ON(path->nodes[level]); | 1256 | BUG_ON(path->nodes[level]); |
1210 | BUG_ON(path->nodes[level-1] != root->node); | 1257 | BUG_ON(path->nodes[level-1] != root->node); |
1211 | 1258 | ||
1212 | c = btrfs_alloc_free_block(trans, root, root->nodesize, | 1259 | if (root->ref_cows) |
1260 | root_gen = trans->transid; | ||
1261 | else | ||
1262 | root_gen = 0; | ||
1263 | |||
1264 | lower = path->nodes[level-1]; | ||
1265 | if (level == 1) | ||
1266 | btrfs_item_key(lower, &lower_key, 0); | ||
1267 | else | ||
1268 | btrfs_node_key(lower, &lower_key, 0); | ||
1269 | |||
1270 | c = __btrfs_alloc_free_block(trans, root, root->nodesize, | ||
1271 | root->root_key.objectid, | ||
1272 | root_gen, lower_key.objectid, level, | ||
1213 | root->node->start, 0); | 1273 | root->node->start, 0); |
1214 | if (IS_ERR(c)) | 1274 | if (IS_ERR(c)) |
1215 | return PTR_ERR(c); | 1275 | return PTR_ERR(c); |
@@ -1219,19 +1279,16 @@ static int insert_new_root(struct btrfs_trans_handle *trans, | |||
1219 | btrfs_set_header_bytenr(c, c->start); | 1279 | btrfs_set_header_bytenr(c, c->start); |
1220 | btrfs_set_header_generation(c, trans->transid); | 1280 | btrfs_set_header_generation(c, trans->transid); |
1221 | btrfs_set_header_owner(c, root->root_key.objectid); | 1281 | btrfs_set_header_owner(c, root->root_key.objectid); |
1222 | lower = path->nodes[level-1]; | ||
1223 | 1282 | ||
1224 | write_extent_buffer(c, root->fs_info->fsid, | 1283 | write_extent_buffer(c, root->fs_info->fsid, |
1225 | (unsigned long)btrfs_header_fsid(c), | 1284 | (unsigned long)btrfs_header_fsid(c), |
1226 | BTRFS_FSID_SIZE); | 1285 | BTRFS_FSID_SIZE); |
1227 | if (level == 1) | ||
1228 | btrfs_item_key(lower, &lower_key, 0); | ||
1229 | else | ||
1230 | btrfs_node_key(lower, &lower_key, 0); | ||
1231 | btrfs_set_node_key(c, &lower_key, 0); | 1286 | btrfs_set_node_key(c, &lower_key, 0); |
1232 | btrfs_set_node_blockptr(c, 0, lower->start); | 1287 | btrfs_set_node_blockptr(c, 0, lower->start); |
1233 | WARN_ON(btrfs_header_generation(lower) == 0); | 1288 | lower_gen = btrfs_header_generation(lower); |
1234 | btrfs_set_node_ptr_generation(c, 0, btrfs_header_generation(lower)); | 1289 | WARN_ON(lower_gen == 0); |
1290 | |||
1291 | btrfs_set_node_ptr_generation(c, 0, lower_gen); | ||
1235 | 1292 | ||
1236 | btrfs_mark_buffer_dirty(c); | 1293 | btrfs_mark_buffer_dirty(c); |
1237 | 1294 | ||
@@ -1241,6 +1298,18 @@ static int insert_new_root(struct btrfs_trans_handle *trans, | |||
1241 | extent_buffer_get(c); | 1298 | extent_buffer_get(c); |
1242 | path->nodes[level] = c; | 1299 | path->nodes[level] = c; |
1243 | path->slots[level] = 0; | 1300 | path->slots[level] = 0; |
1301 | |||
1302 | if (root->ref_cows && lower_gen != trans->transid) { | ||
1303 | struct btrfs_path *back_path = btrfs_alloc_path(); | ||
1304 | int ret; | ||
1305 | ret = btrfs_insert_extent_backref(trans, | ||
1306 | root->fs_info->extent_root, | ||
1307 | path, lower->start, | ||
1308 | root->root_key.objectid, | ||
1309 | trans->transid, 0, 0); | ||
1310 | BUG_ON(ret); | ||
1311 | btrfs_free_path(back_path); | ||
1312 | } | ||
1244 | return 0; | 1313 | return 0; |
1245 | } | 1314 | } |
1246 | 1315 | ||
@@ -1294,6 +1363,7 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1294 | static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root | 1363 | static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root |
1295 | *root, struct btrfs_path *path, int level) | 1364 | *root, struct btrfs_path *path, int level) |
1296 | { | 1365 | { |
1366 | u64 root_gen; | ||
1297 | struct extent_buffer *c; | 1367 | struct extent_buffer *c; |
1298 | struct extent_buffer *split; | 1368 | struct extent_buffer *split; |
1299 | struct btrfs_disk_key disk_key; | 1369 | struct btrfs_disk_key disk_key; |
@@ -1303,6 +1373,7 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1303 | u32 c_nritems; | 1373 | u32 c_nritems; |
1304 | 1374 | ||
1305 | c = path->nodes[level]; | 1375 | c = path->nodes[level]; |
1376 | WARN_ON(btrfs_header_generation(c) != trans->transid); | ||
1306 | if (c == root->node) { | 1377 | if (c == root->node) { |
1307 | /* trying to split the root, lets make a new one */ | 1378 | /* trying to split the root, lets make a new one */ |
1308 | ret = insert_new_root(trans, root, path, level + 1); | 1379 | ret = insert_new_root(trans, root, path, level + 1); |
@@ -1319,8 +1390,17 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1319 | } | 1390 | } |
1320 | 1391 | ||
1321 | c_nritems = btrfs_header_nritems(c); | 1392 | c_nritems = btrfs_header_nritems(c); |
1322 | split = btrfs_alloc_free_block(trans, root, root->nodesize, | 1393 | if (root->ref_cows) |
1323 | c->start, 0); | 1394 | root_gen = trans->transid; |
1395 | else | ||
1396 | root_gen = 0; | ||
1397 | |||
1398 | btrfs_node_key(c, &disk_key, 0); | ||
1399 | split = __btrfs_alloc_free_block(trans, root, root->nodesize, | ||
1400 | root->root_key.objectid, | ||
1401 | root_gen, | ||
1402 | btrfs_disk_key_objectid(&disk_key), | ||
1403 | level, c->start, 0); | ||
1324 | if (IS_ERR(split)) | 1404 | if (IS_ERR(split)) |
1325 | return PTR_ERR(split); | 1405 | return PTR_ERR(split); |
1326 | 1406 | ||
@@ -1789,6 +1869,7 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1789 | *root, struct btrfs_key *ins_key, | 1869 | *root, struct btrfs_key *ins_key, |
1790 | struct btrfs_path *path, int data_size, int extend) | 1870 | struct btrfs_path *path, int data_size, int extend) |
1791 | { | 1871 | { |
1872 | u64 root_gen; | ||
1792 | struct extent_buffer *l; | 1873 | struct extent_buffer *l; |
1793 | u32 nritems; | 1874 | u32 nritems; |
1794 | int mid; | 1875 | int mid; |
@@ -1807,6 +1888,11 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1807 | if (extend) | 1888 | if (extend) |
1808 | space_needed = data_size; | 1889 | space_needed = data_size; |
1809 | 1890 | ||
1891 | if (root->ref_cows) | ||
1892 | root_gen = trans->transid; | ||
1893 | else | ||
1894 | root_gen = 0; | ||
1895 | |||
1810 | /* first try to make some room by pushing left and right */ | 1896 | /* first try to make some room by pushing left and right */ |
1811 | if (ins_key->type != BTRFS_DIR_ITEM_KEY) { | 1897 | if (ins_key->type != BTRFS_DIR_ITEM_KEY) { |
1812 | wret = push_leaf_right(trans, root, path, data_size, 0); | 1898 | wret = push_leaf_right(trans, root, path, data_size, 0); |
@@ -1837,8 +1923,12 @@ again: | |||
1837 | nritems = btrfs_header_nritems(l); | 1923 | nritems = btrfs_header_nritems(l); |
1838 | mid = (nritems + 1)/ 2; | 1924 | mid = (nritems + 1)/ 2; |
1839 | 1925 | ||
1840 | right = btrfs_alloc_free_block(trans, root, root->leafsize, | 1926 | btrfs_item_key(l, &disk_key, 0); |
1841 | l->start, 0); | 1927 | |
1928 | right = __btrfs_alloc_free_block(trans, root, root->leafsize, | ||
1929 | root->root_key.objectid, | ||
1930 | root_gen, disk_key.objectid, 0, | ||
1931 | l->start, 0); | ||
1842 | if (IS_ERR(right)) | 1932 | if (IS_ERR(right)) |
1843 | return PTR_ERR(right); | 1933 | return PTR_ERR(right); |
1844 | 1934 | ||
@@ -2413,13 +2503,16 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
2413 | if (leaf == root->node) { | 2503 | if (leaf == root->node) { |
2414 | btrfs_set_header_level(leaf, 0); | 2504 | btrfs_set_header_level(leaf, 0); |
2415 | } else { | 2505 | } else { |
2506 | u64 root_gen = btrfs_header_generation(path->nodes[1]); | ||
2416 | clean_tree_block(trans, root, leaf); | 2507 | clean_tree_block(trans, root, leaf); |
2417 | wait_on_tree_block_writeback(root, leaf); | 2508 | wait_on_tree_block_writeback(root, leaf); |
2418 | wret = del_ptr(trans, root, path, 1, path->slots[1]); | 2509 | wret = del_ptr(trans, root, path, 1, path->slots[1]); |
2419 | if (wret) | 2510 | if (wret) |
2420 | ret = wret; | 2511 | ret = wret; |
2421 | wret = btrfs_free_extent(trans, root, | 2512 | wret = btrfs_free_extent(trans, root, |
2422 | leaf->start, leaf->len, 1); | 2513 | leaf->start, leaf->len, |
2514 | btrfs_header_owner(path->nodes[1]), | ||
2515 | root_gen, 0, 0, 1); | ||
2423 | if (wret) | 2516 | if (wret) |
2424 | ret = wret; | 2517 | ret = wret; |
2425 | } | 2518 | } |
@@ -2456,9 +2549,13 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
2456 | } | 2549 | } |
2457 | 2550 | ||
2458 | if (btrfs_header_nritems(leaf) == 0) { | 2551 | if (btrfs_header_nritems(leaf) == 0) { |
2552 | u64 root_gen; | ||
2459 | u64 bytenr = leaf->start; | 2553 | u64 bytenr = leaf->start; |
2460 | u32 blocksize = leaf->len; | 2554 | u32 blocksize = leaf->len; |
2461 | 2555 | ||
2556 | root_gen = btrfs_header_generation( | ||
2557 | path->nodes[1]); | ||
2558 | |||
2462 | clean_tree_block(trans, root, leaf); | 2559 | clean_tree_block(trans, root, leaf); |
2463 | wait_on_tree_block_writeback(root, leaf); | 2560 | wait_on_tree_block_writeback(root, leaf); |
2464 | 2561 | ||
@@ -2468,7 +2565,9 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
2468 | 2565 | ||
2469 | free_extent_buffer(leaf); | 2566 | free_extent_buffer(leaf); |
2470 | wret = btrfs_free_extent(trans, root, bytenr, | 2567 | wret = btrfs_free_extent(trans, root, bytenr, |
2471 | blocksize, 1); | 2568 | blocksize, |
2569 | btrfs_header_owner(path->nodes[1]), | ||
2570 | root_gen, 0, 0, 1); | ||
2472 | if (wret) | 2571 | if (wret) |
2473 | ret = wret; | 2572 | ret = wret; |
2474 | } else { | 2573 | } else { |
@@ -2483,6 +2582,61 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
2483 | } | 2582 | } |
2484 | 2583 | ||
2485 | /* | 2584 | /* |
2585 | * walk up the tree as far as required to find the previous leaf. | ||
2586 | * returns 0 if it found something or 1 if there are no lesser leaves. | ||
2587 | * returns < 0 on io errors. | ||
2588 | */ | ||
2589 | int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path) | ||
2590 | { | ||
2591 | int slot; | ||
2592 | int level = 1; | ||
2593 | u64 bytenr; | ||
2594 | struct extent_buffer *c; | ||
2595 | struct extent_buffer *next = NULL; | ||
2596 | |||
2597 | while(level < BTRFS_MAX_LEVEL) { | ||
2598 | if (!path->nodes[level]) | ||
2599 | return 1; | ||
2600 | |||
2601 | slot = path->slots[level]; | ||
2602 | c = path->nodes[level]; | ||
2603 | if (slot == 0) { | ||
2604 | level++; | ||
2605 | if (level == BTRFS_MAX_LEVEL) | ||
2606 | return 1; | ||
2607 | continue; | ||
2608 | } | ||
2609 | slot--; | ||
2610 | |||
2611 | bytenr = btrfs_node_blockptr(c, slot); | ||
2612 | if (next) | ||
2613 | free_extent_buffer(next); | ||
2614 | |||
2615 | if (path->reada < 0) | ||
2616 | reada_for_search(root, path, level, slot); | ||
2617 | |||
2618 | next = read_tree_block(root, bytenr, | ||
2619 | btrfs_level_size(root, level - 1)); | ||
2620 | break; | ||
2621 | } | ||
2622 | path->slots[level] = slot; | ||
2623 | while(1) { | ||
2624 | level--; | ||
2625 | c = path->nodes[level]; | ||
2626 | free_extent_buffer(c); | ||
2627 | path->nodes[level] = next; | ||
2628 | path->slots[level] = 0; | ||
2629 | if (!level) | ||
2630 | break; | ||
2631 | if (path->reada) | ||
2632 | reada_for_search(root, path, level, 0); | ||
2633 | next = read_tree_block(root, btrfs_node_blockptr(next, 0), | ||
2634 | btrfs_level_size(root, level - 1)); | ||
2635 | } | ||
2636 | return 0; | ||
2637 | } | ||
2638 | |||
2639 | /* | ||
2486 | * walk up the tree as far as required to find the next leaf. | 2640 | * walk up the tree as far as required to find the next leaf. |
2487 | * returns 0 if it found something or 1 if there are no greater leaves. | 2641 | * returns 0 if it found something or 1 if there are no greater leaves. |
2488 | * returns < 0 on io errors. | 2642 | * returns < 0 on io errors. |
@@ -2503,6 +2657,8 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) | |||
2503 | c = path->nodes[level]; | 2657 | c = path->nodes[level]; |
2504 | if (slot >= btrfs_header_nritems(c)) { | 2658 | if (slot >= btrfs_header_nritems(c)) { |
2505 | level++; | 2659 | level++; |
2660 | if (level == BTRFS_MAX_LEVEL) | ||
2661 | return 1; | ||
2506 | continue; | 2662 | continue; |
2507 | } | 2663 | } |
2508 | 2664 | ||
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index fd58dd846e61..cb1b156d954e 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -544,11 +544,12 @@ BTRFS_SETGET_FUNCS(ref_generation, struct btrfs_extent_ref, generation, 64); | |||
544 | BTRFS_SETGET_FUNCS(ref_objectid, struct btrfs_extent_ref, objectid, 64); | 544 | BTRFS_SETGET_FUNCS(ref_objectid, struct btrfs_extent_ref, objectid, 64); |
545 | BTRFS_SETGET_FUNCS(ref_offset, struct btrfs_extent_ref, offset, 64); | 545 | BTRFS_SETGET_FUNCS(ref_offset, struct btrfs_extent_ref, offset, 64); |
546 | 546 | ||
547 | BTRFS_SETGET_STACK_FUNCS(ref_root, struct btrfs_extent_ref, root, 64); | 547 | BTRFS_SETGET_STACK_FUNCS(stack_ref_root, struct btrfs_extent_ref, root, 64); |
548 | BTRFS_SETGET_STACK_FUNCS(ref_generation, struct btrfs_extent_ref, | 548 | BTRFS_SETGET_STACK_FUNCS(stack_ref_generation, struct btrfs_extent_ref, |
549 | generation, 64); | 549 | generation, 64); |
550 | BTRFS_SETGET_STACK_FUNCS(ref_objectid, struct btrfs_extent_ref, objectid, 64); | 550 | BTRFS_SETGET_STACK_FUNCS(stack_ref_objectid, struct btrfs_extent_ref, |
551 | BTRFS_SETGET_STACK_FUNCS(ref_offset, struct btrfs_extent_ref, offset, 64); | 551 | objectid, 64); |
552 | BTRFS_SETGET_STACK_FUNCS(stack_ref_offset, struct btrfs_extent_ref, offset, 64); | ||
552 | 553 | ||
553 | BTRFS_SETGET_STACK_FUNCS(stack_extent_refs, struct btrfs_extent_item, | 554 | BTRFS_SETGET_STACK_FUNCS(stack_extent_refs, struct btrfs_extent_item, |
554 | refs, 32); | 555 | refs, 32); |
@@ -914,24 +915,45 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, | |||
914 | *hint, u64 search_start, | 915 | *hint, u64 search_start, |
915 | int data, int owner); | 916 | int data, int owner); |
916 | int btrfs_inc_root_ref(struct btrfs_trans_handle *trans, | 917 | int btrfs_inc_root_ref(struct btrfs_trans_handle *trans, |
917 | struct btrfs_root *root); | 918 | struct btrfs_root *root, u64 owner_objectid); |
918 | struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | 919 | struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, |
919 | struct btrfs_root *root, u32 size, | 920 | struct btrfs_root *root, u32 size, |
921 | u64 root_objectid, | ||
920 | u64 hint, u64 empty_size); | 922 | u64 hint, u64 empty_size); |
923 | struct extent_buffer *__btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | ||
924 | struct btrfs_root *root, | ||
925 | u32 blocksize, | ||
926 | u64 root_objectid, | ||
927 | u64 ref_generation, | ||
928 | u64 first_objectid, | ||
929 | int level, | ||
930 | u64 hint, | ||
931 | u64 empty_size); | ||
932 | int btrfs_insert_extent_backref(struct btrfs_trans_handle *trans, | ||
933 | struct btrfs_root *root, | ||
934 | struct btrfs_path *path, u64 bytenr, | ||
935 | u64 root_objectid, u64 ref_generation, | ||
936 | u64 owner, u64 owner_offset); | ||
921 | int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | 937 | int btrfs_alloc_extent(struct btrfs_trans_handle *trans, |
922 | struct btrfs_root *root, u64 owner, | 938 | struct btrfs_root *root, |
923 | u64 num_bytes, u64 empty_size, u64 search_start, | 939 | u64 num_bytes, u64 root_objectid, u64 ref_generation, |
940 | u64 owner, u64 owner_offset, | ||
941 | u64 empty_size, u64 hint_byte, | ||
924 | u64 search_end, struct btrfs_key *ins, int data); | 942 | u64 search_end, struct btrfs_key *ins, int data); |
925 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 943 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
926 | struct extent_buffer *buf); | 944 | struct extent_buffer *buf); |
927 | int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | 945 | int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root |
928 | *root, u64 bytenr, u64 num_bytes, int pin); | 946 | *root, u64 bytenr, u64 num_bytes, |
947 | u64 root_objectid, u64 ref_generation, | ||
948 | u64 owner_objectid, u64 owner_offset, int pin); | ||
929 | int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, | 949 | int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, |
930 | struct btrfs_root *root, | 950 | struct btrfs_root *root, |
931 | struct extent_map_tree *unpin); | 951 | struct extent_map_tree *unpin); |
932 | int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, | 952 | int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, |
933 | struct btrfs_root *root, | 953 | struct btrfs_root *root, |
934 | u64 bytenr, u64 num_bytes); | 954 | u64 bytenr, u64 num_bytes, |
955 | u64 root_objectid, u64 ref_generation, | ||
956 | u64 owner, u64 owner_offset); | ||
935 | int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, | 957 | int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, |
936 | struct btrfs_root *root); | 958 | struct btrfs_root *root); |
937 | int btrfs_free_block_groups(struct btrfs_fs_info *info); | 959 | int btrfs_free_block_groups(struct btrfs_fs_info *info); |
@@ -966,6 +988,7 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
966 | *root, struct btrfs_path *path, struct btrfs_key | 988 | *root, struct btrfs_path *path, struct btrfs_key |
967 | *cpu_key, u32 data_size); | 989 | *cpu_key, u32 data_size); |
968 | int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path); | 990 | int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path); |
991 | int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path); | ||
969 | int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf); | 992 | int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf); |
970 | int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root | 993 | int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root |
971 | *root); | 994 | *root); |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 60a30da6af00..0ac21e3aac87 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -210,7 +210,7 @@ static int btree_writepages(struct address_space *mapping, | |||
210 | { | 210 | { |
211 | struct extent_map_tree *tree; | 211 | struct extent_map_tree *tree; |
212 | tree = &BTRFS_I(mapping->host)->extent_tree; | 212 | tree = &BTRFS_I(mapping->host)->extent_tree; |
213 | if (wbc->sync_mode == WB_SYNC_NONE) { | 213 | if (0 && wbc->sync_mode == WB_SYNC_NONE) { |
214 | u64 num_dirty; | 214 | u64 num_dirty; |
215 | u64 start = 0; | 215 | u64 start = 0; |
216 | unsigned long thresh = 96 * 1024 * 1024; | 216 | unsigned long thresh = 96 * 1024 * 1024; |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 0f1ebdd4e925..32991f73e9db 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -17,6 +17,7 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
20 | #include <linux/crc32c.h> | ||
20 | #include "hash.h" | 21 | #include "hash.h" |
21 | #include "ctree.h" | 22 | #include "ctree.h" |
22 | #include "disk-io.h" | 23 | #include "disk-io.h" |
@@ -89,7 +90,8 @@ static int cache_block_group(struct btrfs_root *root, | |||
89 | 90 | ||
90 | btrfs_item_key_to_cpu(leaf, &key, slot); | 91 | btrfs_item_key_to_cpu(leaf, &key, slot); |
91 | if (key.objectid < block_group->key.objectid) { | 92 | if (key.objectid < block_group->key.objectid) { |
92 | if (key.objectid + key.offset > first_free) | 93 | if (btrfs_key_type(&key) != BTRFS_EXTENT_REF_KEY && |
94 | key.objectid + key.offset > first_free) | ||
93 | first_free = key.objectid + key.offset; | 95 | first_free = key.objectid + key.offset; |
94 | goto next; | 96 | goto next; |
95 | } | 97 | } |
@@ -353,7 +355,7 @@ found: | |||
353 | return found_group; | 355 | return found_group; |
354 | } | 356 | } |
355 | 357 | ||
356 | static u64 hash_extent_ref(u64 root_objectid, u64 root_generation, | 358 | static u64 hash_extent_ref(u64 root_objectid, u64 ref_generation, |
357 | u64 owner, u64 owner_offset) | 359 | u64 owner, u64 owner_offset) |
358 | { | 360 | { |
359 | u32 high_crc = ~(u32)0; | 361 | u32 high_crc = ~(u32)0; |
@@ -362,53 +364,149 @@ static u64 hash_extent_ref(u64 root_objectid, u64 root_generation, | |||
362 | 364 | ||
363 | lenum = cpu_to_le64(root_objectid); | 365 | lenum = cpu_to_le64(root_objectid); |
364 | high_crc = crc32c(high_crc, &lenum, sizeof(lenum)); | 366 | high_crc = crc32c(high_crc, &lenum, sizeof(lenum)); |
365 | lenum = cpu_to_le64(root_generation); | 367 | lenum = cpu_to_le64(ref_generation); |
366 | high_crc = crc32c(high_crc, &lenum, sizeof(lenum)); | 368 | low_crc = crc32c(low_crc, &lenum, sizeof(lenum)); |
367 | 369 | ||
370 | #if 0 | ||
368 | lenum = cpu_to_le64(owner); | 371 | lenum = cpu_to_le64(owner); |
369 | low_crc = crc32c(low_crc, &lenum, sizeof(lenum)); | 372 | low_crc = crc32c(low_crc, &lenum, sizeof(lenum)); |
370 | |||
371 | lenum = cpu_to_le64(owner_offset); | 373 | lenum = cpu_to_le64(owner_offset); |
372 | low_crc = crc32c(low_crc, &lenum, sizeof(lenum)); | 374 | low_crc = crc32c(low_crc, &lenum, sizeof(lenum)); |
373 | 375 | #endif | |
374 | return ((u64)high_crc << 32) | (u64)low_crc; | 376 | return ((u64)high_crc << 32) | (u64)low_crc; |
375 | } | 377 | } |
376 | 378 | ||
377 | int insert_extent_ref(struct btrfs_trans_handle *trans, | 379 | static int match_extent_ref(struct extent_buffer *leaf, |
378 | struct btrfs_root *root, | 380 | struct btrfs_extent_ref *disk_ref, |
379 | struct btrfs_path *path, | 381 | struct btrfs_extent_ref *cpu_ref) |
380 | u64 bytenr, | 382 | { |
381 | u64 root_objectid, u64 root_generation, | 383 | int ret; |
382 | u64 owner, u64 owner_offset) | 384 | int len; |
385 | |||
386 | if (cpu_ref->objectid) | ||
387 | len = sizeof(*cpu_ref); | ||
388 | else | ||
389 | len = 2 * sizeof(u64); | ||
390 | ret = memcmp_extent_buffer(leaf, cpu_ref, (unsigned long)disk_ref, | ||
391 | len); | ||
392 | return ret == 0; | ||
393 | } | ||
394 | |||
395 | static int lookup_extent_backref(struct btrfs_trans_handle *trans, | ||
396 | struct btrfs_root *root, | ||
397 | struct btrfs_path *path, u64 bytenr, | ||
398 | u64 root_objectid, u64 ref_generation, | ||
399 | u64 owner, u64 owner_offset, int del) | ||
383 | { | 400 | { |
384 | u64 hash; | 401 | u64 hash; |
385 | struct btrfs_key key; | 402 | struct btrfs_key key; |
403 | struct btrfs_key found_key; | ||
386 | struct btrfs_extent_ref ref; | 404 | struct btrfs_extent_ref ref; |
387 | struct extent_buffer *l; | 405 | struct extent_buffer *leaf; |
388 | struct btrfs_extent_item *item; | 406 | struct btrfs_extent_ref *disk_ref; |
407 | int ret; | ||
408 | int ret2; | ||
409 | |||
410 | btrfs_set_stack_ref_root(&ref, root_objectid); | ||
411 | btrfs_set_stack_ref_generation(&ref, ref_generation); | ||
412 | btrfs_set_stack_ref_objectid(&ref, owner); | ||
413 | btrfs_set_stack_ref_offset(&ref, owner_offset); | ||
414 | |||
415 | hash = hash_extent_ref(root_objectid, ref_generation, owner, | ||
416 | owner_offset); | ||
417 | key.offset = hash; | ||
418 | key.objectid = bytenr; | ||
419 | key.type = BTRFS_EXTENT_REF_KEY; | ||
420 | |||
421 | while (1) { | ||
422 | ret = btrfs_search_slot(trans, root, &key, path, | ||
423 | del ? -1 : 0, del); | ||
424 | if (ret < 0) | ||
425 | goto out; | ||
426 | leaf = path->nodes[0]; | ||
427 | if (ret != 0) { | ||
428 | u32 nritems = btrfs_header_nritems(leaf); | ||
429 | if (path->slots[0] >= nritems) { | ||
430 | ret2 = btrfs_next_leaf(root, path); | ||
431 | if (ret2) | ||
432 | goto out; | ||
433 | leaf = path->nodes[0]; | ||
434 | } | ||
435 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); | ||
436 | if (found_key.objectid != bytenr || | ||
437 | found_key.type != BTRFS_EXTENT_REF_KEY) | ||
438 | goto out; | ||
439 | key.offset = found_key.offset; | ||
440 | if (del) { | ||
441 | btrfs_release_path(root, path); | ||
442 | continue; | ||
443 | } | ||
444 | } | ||
445 | disk_ref = btrfs_item_ptr(path->nodes[0], | ||
446 | path->slots[0], | ||
447 | struct btrfs_extent_ref); | ||
448 | if (match_extent_ref(path->nodes[0], disk_ref, &ref)) { | ||
449 | ret = 0; | ||
450 | goto out; | ||
451 | } | ||
452 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); | ||
453 | key.offset = found_key.offset + 1; | ||
454 | btrfs_release_path(root, path); | ||
455 | } | ||
456 | out: | ||
457 | return ret; | ||
458 | } | ||
459 | |||
460 | int btrfs_insert_extent_backref(struct btrfs_trans_handle *trans, | ||
461 | struct btrfs_root *root, | ||
462 | struct btrfs_path *path, u64 bytenr, | ||
463 | u64 root_objectid, u64 ref_generation, | ||
464 | u64 owner, u64 owner_offset) | ||
465 | { | ||
466 | u64 hash; | ||
467 | struct btrfs_key key; | ||
468 | struct btrfs_extent_ref ref; | ||
469 | struct btrfs_extent_ref *disk_ref; | ||
389 | int ret; | 470 | int ret; |
390 | 471 | ||
391 | btrfs_set_stack_ref_root(&ref, root_objectid); | 472 | btrfs_set_stack_ref_root(&ref, root_objectid); |
392 | btrfs_set_stack_ref_generation(&ref, root_generation); | 473 | btrfs_set_stack_ref_generation(&ref, ref_generation); |
393 | btrfs_set_stack_ref_objectid(&ref, owner); | 474 | btrfs_set_stack_ref_objectid(&ref, owner); |
394 | btrfs_set_stack_ref_offset(&ref, owner_offset); | 475 | btrfs_set_stack_ref_offset(&ref, owner_offset); |
395 | 476 | ||
396 | ret = btrfs_name_hash(&ref, sizeof(ref), &hash); | 477 | hash = hash_extent_ref(root_objectid, ref_generation, owner, |
478 | owner_offset); | ||
397 | key.offset = hash; | 479 | key.offset = hash; |
398 | key.objectid = bytenr; | 480 | key.objectid = bytenr; |
399 | key.type = BTRFS_EXTENT_REF_KEY; | 481 | key.type = BTRFS_EXTENT_REF_KEY; |
400 | 482 | ||
401 | ret = btrfs_insert_empty_item(trans, root, path, &key, sizeof(ref)); | 483 | ret = btrfs_insert_empty_item(trans, root, path, &key, sizeof(ref)); |
402 | while (ret == -EEXIST) { | 484 | while (ret == -EEXIST) { |
403 | 485 | disk_ref = btrfs_item_ptr(path->nodes[0], path->slots[0], | |
486 | struct btrfs_extent_ref); | ||
487 | if (match_extent_ref(path->nodes[0], disk_ref, &ref)) | ||
488 | goto out; | ||
489 | key.offset++; | ||
490 | btrfs_release_path(root, path); | ||
491 | ret = btrfs_insert_empty_item(trans, root, path, &key, | ||
492 | sizeof(ref)); | ||
404 | } | 493 | } |
405 | 494 | if (ret) | |
495 | goto out; | ||
496 | disk_ref = btrfs_item_ptr(path->nodes[0], path->slots[0], | ||
497 | struct btrfs_extent_ref); | ||
498 | write_extent_buffer(path->nodes[0], &ref, (unsigned long)disk_ref, | ||
499 | sizeof(ref)); | ||
500 | btrfs_mark_buffer_dirty(path->nodes[0]); | ||
501 | out: | ||
502 | btrfs_release_path(root, path); | ||
503 | return ret; | ||
406 | } | 504 | } |
407 | 505 | ||
408 | int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, | 506 | int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, |
409 | struct btrfs_root *root, | 507 | struct btrfs_root *root, |
410 | u64 bytenr, u64 num_bytes, | 508 | u64 bytenr, u64 num_bytes, |
411 | u64 root_objectid, u64 root_generation, | 509 | u64 root_objectid, u64 ref_generation, |
412 | u64 owner, u64 owner_offset) | 510 | u64 owner, u64 owner_offset) |
413 | { | 511 | { |
414 | struct btrfs_path *path; | 512 | struct btrfs_path *path; |
@@ -441,6 +539,11 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, | |||
441 | btrfs_mark_buffer_dirty(path->nodes[0]); | 539 | btrfs_mark_buffer_dirty(path->nodes[0]); |
442 | 540 | ||
443 | btrfs_release_path(root->fs_info->extent_root, path); | 541 | btrfs_release_path(root->fs_info->extent_root, path); |
542 | |||
543 | ret = btrfs_insert_extent_backref(trans, root->fs_info->extent_root, | ||
544 | path, bytenr, root_objectid, | ||
545 | ref_generation, owner, owner_offset); | ||
546 | BUG_ON(ret); | ||
444 | finish_current_insert(trans, root->fs_info->extent_root); | 547 | finish_current_insert(trans, root->fs_info->extent_root); |
445 | del_pending_extents(trans, root->fs_info->extent_root); | 548 | del_pending_extents(trans, root->fs_info->extent_root); |
446 | 549 | ||
@@ -489,10 +592,29 @@ out: | |||
489 | } | 592 | } |
490 | 593 | ||
491 | int btrfs_inc_root_ref(struct btrfs_trans_handle *trans, | 594 | int btrfs_inc_root_ref(struct btrfs_trans_handle *trans, |
492 | struct btrfs_root *root) | 595 | struct btrfs_root *root, u64 owner_objectid) |
493 | { | 596 | { |
597 | u64 generation; | ||
598 | u64 key_objectid; | ||
599 | u64 level; | ||
600 | u32 nritems; | ||
601 | struct btrfs_disk_key disk_key; | ||
602 | |||
603 | level = btrfs_header_level(root->node); | ||
604 | generation = trans->transid; | ||
605 | nritems = btrfs_header_nritems(root->node); | ||
606 | if (nritems > 0) { | ||
607 | if (level == 0) | ||
608 | btrfs_item_key(root->node, &disk_key, 0); | ||
609 | else | ||
610 | btrfs_node_key(root->node, &disk_key, 0); | ||
611 | key_objectid = btrfs_disk_key_objectid(&disk_key); | ||
612 | } else { | ||
613 | key_objectid = 0; | ||
614 | } | ||
494 | return btrfs_inc_extent_ref(trans, root, root->node->start, | 615 | return btrfs_inc_extent_ref(trans, root, root->node->start, |
495 | root->node->len); | 616 | root->node->len, owner_objectid, |
617 | generation, 0, 0); | ||
496 | } | 618 | } |
497 | 619 | ||
498 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 620 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
@@ -506,7 +628,6 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
506 | int level; | 628 | int level; |
507 | int ret; | 629 | int ret; |
508 | int faili; | 630 | int faili; |
509 | int err; | ||
510 | 631 | ||
511 | if (!root->ref_cows) | 632 | if (!root->ref_cows) |
512 | return 0; | 633 | return 0; |
@@ -528,7 +649,9 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
528 | if (disk_bytenr == 0) | 649 | if (disk_bytenr == 0) |
529 | continue; | 650 | continue; |
530 | ret = btrfs_inc_extent_ref(trans, root, disk_bytenr, | 651 | ret = btrfs_inc_extent_ref(trans, root, disk_bytenr, |
531 | btrfs_file_extent_disk_num_bytes(buf, fi)); | 652 | btrfs_file_extent_disk_num_bytes(buf, fi), |
653 | root->root_key.objectid, trans->transid, | ||
654 | key.objectid, key.offset); | ||
532 | if (ret) { | 655 | if (ret) { |
533 | faili = i; | 656 | faili = i; |
534 | goto fail; | 657 | goto fail; |
@@ -536,7 +659,9 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
536 | } else { | 659 | } else { |
537 | bytenr = btrfs_node_blockptr(buf, i); | 660 | bytenr = btrfs_node_blockptr(buf, i); |
538 | ret = btrfs_inc_extent_ref(trans, root, bytenr, | 661 | ret = btrfs_inc_extent_ref(trans, root, bytenr, |
539 | btrfs_level_size(root, level - 1)); | 662 | btrfs_level_size(root, level - 1), |
663 | root->root_key.objectid, | ||
664 | trans->transid, 0, 0); | ||
540 | if (ret) { | 665 | if (ret) { |
541 | faili = i; | 666 | faili = i; |
542 | goto fail; | 667 | goto fail; |
@@ -546,6 +671,7 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
546 | return 0; | 671 | return 0; |
547 | fail: | 672 | fail: |
548 | WARN_ON(1); | 673 | WARN_ON(1); |
674 | #if 0 | ||
549 | for (i =0; i < faili; i++) { | 675 | for (i =0; i < faili; i++) { |
550 | if (level == 0) { | 676 | if (level == 0) { |
551 | u64 disk_bytenr; | 677 | u64 disk_bytenr; |
@@ -571,6 +697,7 @@ fail: | |||
571 | BUG_ON(err); | 697 | BUG_ON(err); |
572 | } | 698 | } |
573 | } | 699 | } |
700 | #endif | ||
574 | return ret; | 701 | return ret; |
575 | } | 702 | } |
576 | 703 | ||
@@ -809,18 +936,18 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, | |||
809 | static int finish_current_insert(struct btrfs_trans_handle *trans, struct | 936 | static int finish_current_insert(struct btrfs_trans_handle *trans, struct |
810 | btrfs_root *extent_root) | 937 | btrfs_root *extent_root) |
811 | { | 938 | { |
939 | u64 start; | ||
940 | u64 end; | ||
941 | struct btrfs_fs_info *info = extent_root->fs_info; | ||
942 | struct btrfs_path *path; | ||
812 | struct btrfs_key ins; | 943 | struct btrfs_key ins; |
813 | struct btrfs_extent_item extent_item; | 944 | struct btrfs_extent_item extent_item; |
814 | int ret; | 945 | int ret; |
815 | int err = 0; | 946 | int err = 0; |
816 | u64 start; | ||
817 | u64 end; | ||
818 | struct btrfs_fs_info *info = extent_root->fs_info; | ||
819 | 947 | ||
820 | btrfs_set_stack_extent_refs(&extent_item, 1); | 948 | btrfs_set_stack_extent_refs(&extent_item, 1); |
821 | btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY); | 949 | btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY); |
822 | btrfs_set_stack_extent_owner(&extent_item, | 950 | path = btrfs_alloc_path(); |
823 | extent_root->root_key.objectid); | ||
824 | 951 | ||
825 | while(1) { | 952 | while(1) { |
826 | ret = find_first_extent_bit(&info->extent_ins, 0, &start, | 953 | ret = find_first_extent_bit(&info->extent_ins, 0, &start, |
@@ -834,7 +961,12 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct | |||
834 | &extent_item, sizeof(extent_item)); | 961 | &extent_item, sizeof(extent_item)); |
835 | clear_extent_bits(&info->extent_ins, start, end, EXTENT_LOCKED, | 962 | clear_extent_bits(&info->extent_ins, start, end, EXTENT_LOCKED, |
836 | GFP_NOFS); | 963 | GFP_NOFS); |
964 | err = btrfs_insert_extent_backref(trans, extent_root, path, | ||
965 | start, extent_root->root_key.objectid, | ||
966 | 0, 0, 0); | ||
967 | BUG_ON(err); | ||
837 | } | 968 | } |
969 | btrfs_free_path(path); | ||
838 | return 0; | 970 | return 0; |
839 | } | 971 | } |
840 | 972 | ||
@@ -871,7 +1003,9 @@ static int pin_down_bytes(struct btrfs_root *root, u64 bytenr, u32 num_bytes, | |||
871 | * remove an extent from the root, returns 0 on success | 1003 | * remove an extent from the root, returns 0 on success |
872 | */ | 1004 | */ |
873 | static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | 1005 | static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root |
874 | *root, u64 bytenr, u64 num_bytes, int pin, | 1006 | *root, u64 bytenr, u64 num_bytes, |
1007 | u64 root_objectid, u64 ref_generation, | ||
1008 | u64 owner_objectid, u64 owner_offset, int pin, | ||
875 | int mark_free) | 1009 | int mark_free) |
876 | { | 1010 | { |
877 | struct btrfs_path *path; | 1011 | struct btrfs_path *path; |
@@ -891,6 +1025,24 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
891 | if (!path) | 1025 | if (!path) |
892 | return -ENOMEM; | 1026 | return -ENOMEM; |
893 | 1027 | ||
1028 | if (ref_generation && owner_objectid == 0 && root_objectid == 3) { | ||
1029 | //printk("drop backref root %Lu gen %Lu byte %Lu\n", root_objectid, ref_generation, bytenr ); | ||
1030 | } | ||
1031 | ret = lookup_extent_backref(trans, extent_root, path, | ||
1032 | bytenr, root_objectid, | ||
1033 | ref_generation, | ||
1034 | owner_objectid, owner_offset, 1); | ||
1035 | if (ret == 0) { | ||
1036 | ret = btrfs_del_item(trans, extent_root, path); | ||
1037 | } else { | ||
1038 | btrfs_print_leaf(extent_root, path->nodes[0]); | ||
1039 | WARN_ON(1); | ||
1040 | printk("Unable to find ref byte nr %Lu root %Lu " | ||
1041 | " gen %Lu owner %Lu offset %Lu\n", bytenr, | ||
1042 | root_objectid, ref_generation, owner_objectid, | ||
1043 | owner_offset); | ||
1044 | } | ||
1045 | btrfs_release_path(extent_root, path); | ||
894 | ret = btrfs_search_slot(trans, extent_root, &key, path, -1, 1); | 1046 | ret = btrfs_search_slot(trans, extent_root, &key, path, -1, 1); |
895 | if (ret < 0) | 1047 | if (ret < 0) |
896 | return ret; | 1048 | return ret; |
@@ -965,7 +1117,9 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct | |||
965 | clear_extent_bits(pending_del, start, end, EXTENT_LOCKED, | 1117 | clear_extent_bits(pending_del, start, end, EXTENT_LOCKED, |
966 | GFP_NOFS); | 1118 | GFP_NOFS); |
967 | ret = __free_extent(trans, extent_root, | 1119 | ret = __free_extent(trans, extent_root, |
968 | start, end + 1 - start, 0, 0); | 1120 | start, end + 1 - start, |
1121 | extent_root->root_key.objectid, | ||
1122 | 0, 0, 0, 0, 0); | ||
969 | if (ret) | 1123 | if (ret) |
970 | err = ret; | 1124 | err = ret; |
971 | } | 1125 | } |
@@ -976,18 +1130,25 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct | |||
976 | * remove an extent from the root, returns 0 on success | 1130 | * remove an extent from the root, returns 0 on success |
977 | */ | 1131 | */ |
978 | int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | 1132 | int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root |
979 | *root, u64 bytenr, u64 num_bytes, int pin) | 1133 | *root, u64 bytenr, u64 num_bytes, |
1134 | u64 root_objectid, u64 ref_generation, | ||
1135 | u64 owner_objectid, u64 owner_offset, int pin) | ||
980 | { | 1136 | { |
981 | struct btrfs_root *extent_root = root->fs_info->extent_root; | 1137 | struct btrfs_root *extent_root = root->fs_info->extent_root; |
982 | int pending_ret; | 1138 | int pending_ret; |
983 | int ret; | 1139 | int ret; |
984 | 1140 | ||
985 | WARN_ON(num_bytes < root->sectorsize); | 1141 | WARN_ON(num_bytes < root->sectorsize); |
1142 | if (!root->ref_cows) | ||
1143 | ref_generation = 0; | ||
1144 | |||
986 | if (root == extent_root) { | 1145 | if (root == extent_root) { |
987 | pin_down_bytes(root, bytenr, num_bytes, 1); | 1146 | pin_down_bytes(root, bytenr, num_bytes, 1); |
988 | return 0; | 1147 | return 0; |
989 | } | 1148 | } |
990 | ret = __free_extent(trans, root, bytenr, num_bytes, pin, pin == 0); | 1149 | ret = __free_extent(trans, root, bytenr, num_bytes, root_objectid, |
1150 | ref_generation, owner_objectid, owner_offset, | ||
1151 | pin, pin == 0); | ||
991 | pending_ret = del_pending_extents(trans, root->fs_info->extent_root); | 1152 | pending_ret = del_pending_extents(trans, root->fs_info->extent_root); |
992 | return ret ? ret : pending_ret; | 1153 | return ret ? ret : pending_ret; |
993 | } | 1154 | } |
@@ -1080,23 +1241,26 @@ check_failed: | |||
1080 | btrfs_item_key_to_cpu(l, &key, path->slots[0]); | 1241 | btrfs_item_key_to_cpu(l, &key, path->slots[0]); |
1081 | 1242 | ||
1082 | /* | 1243 | /* |
1083 | * a rare case, go back one key if we hit a block group item | 1244 | * walk backwards to find the first extent item key |
1084 | * instead of an extent item | ||
1085 | */ | 1245 | */ |
1086 | if (btrfs_key_type(&key) != BTRFS_EXTENT_ITEM_KEY && | 1246 | while(btrfs_key_type(&key) != BTRFS_EXTENT_ITEM_KEY) { |
1087 | key.objectid + key.offset >= search_start) { | 1247 | if (path->slots[0] == 0) { |
1088 | ins->objectid = key.objectid; | 1248 | ret = btrfs_prev_leaf(root, path); |
1089 | ins->offset = key.offset - 1; | 1249 | if (ret != 0) { |
1090 | btrfs_release_path(root, path); | 1250 | ret = btrfs_search_slot(trans, root, ins, |
1091 | ret = btrfs_search_slot(trans, root, ins, path, 0, 0); | 1251 | path, 0, 0); |
1092 | if (ret < 0) | 1252 | if (ret < 0) |
1093 | goto error; | 1253 | goto error; |
1094 | 1254 | if (path->slots[0] > 0) | |
1095 | if (path->slots[0] > 0) { | 1255 | path->slots[0]--; |
1256 | break; | ||
1257 | } | ||
1258 | } else { | ||
1096 | path->slots[0]--; | 1259 | path->slots[0]--; |
1097 | } | 1260 | } |
1261 | l = path->nodes[0]; | ||
1262 | btrfs_item_key_to_cpu(l, &key, path->slots[0]); | ||
1098 | } | 1263 | } |
1099 | |||
1100 | while (1) { | 1264 | while (1) { |
1101 | l = path->nodes[0]; | 1265 | l = path->nodes[0]; |
1102 | slot = path->slots[0]; | 1266 | slot = path->slots[0]; |
@@ -1146,7 +1310,8 @@ check_failed: | |||
1146 | } | 1310 | } |
1147 | } | 1311 | } |
1148 | if (btrfs_key_type(&key) != BTRFS_EXTENT_ITEM_KEY) { | 1312 | if (btrfs_key_type(&key) != BTRFS_EXTENT_ITEM_KEY) { |
1149 | if (!start_found) { | 1313 | if (!start_found && btrfs_key_type(&key) == |
1314 | BTRFS_BLOCK_GROUP_ITEM_KEY) { | ||
1150 | last_byte = key.objectid; | 1315 | last_byte = key.objectid; |
1151 | start_found = 1; | 1316 | start_found = 1; |
1152 | } | 1317 | } |
@@ -1244,8 +1409,10 @@ error: | |||
1244 | * returns 0 if everything worked, non-zero otherwise. | 1409 | * returns 0 if everything worked, non-zero otherwise. |
1245 | */ | 1410 | */ |
1246 | int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | 1411 | int btrfs_alloc_extent(struct btrfs_trans_handle *trans, |
1247 | struct btrfs_root *root, u64 owner, | 1412 | struct btrfs_root *root, |
1248 | u64 num_bytes, u64 empty_size, u64 hint_byte, | 1413 | u64 num_bytes, u64 root_objectid, u64 ref_generation, |
1414 | u64 owner, u64 owner_offset, | ||
1415 | u64 empty_size, u64 hint_byte, | ||
1249 | u64 search_end, struct btrfs_key *ins, int data) | 1416 | u64 search_end, struct btrfs_key *ins, int data) |
1250 | { | 1417 | { |
1251 | int ret; | 1418 | int ret; |
@@ -1255,9 +1422,9 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
1255 | struct btrfs_fs_info *info = root->fs_info; | 1422 | struct btrfs_fs_info *info = root->fs_info; |
1256 | struct btrfs_root *extent_root = info->extent_root; | 1423 | struct btrfs_root *extent_root = info->extent_root; |
1257 | struct btrfs_extent_item extent_item; | 1424 | struct btrfs_extent_item extent_item; |
1425 | struct btrfs_path *path; | ||
1258 | 1426 | ||
1259 | btrfs_set_stack_extent_refs(&extent_item, 1); | 1427 | btrfs_set_stack_extent_refs(&extent_item, 1); |
1260 | btrfs_set_stack_extent_owner(&extent_item, owner); | ||
1261 | 1428 | ||
1262 | WARN_ON(num_bytes < root->sectorsize); | 1429 | WARN_ON(num_bytes < root->sectorsize); |
1263 | ret = find_free_extent(trans, root, num_bytes, empty_size, | 1430 | ret = find_free_extent(trans, root, num_bytes, empty_size, |
@@ -1296,8 +1463,16 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
1296 | 1463 | ||
1297 | trans->alloc_exclude_start = 0; | 1464 | trans->alloc_exclude_start = 0; |
1298 | trans->alloc_exclude_nr = 0; | 1465 | trans->alloc_exclude_nr = 0; |
1466 | BUG_ON(ret); | ||
1467 | |||
1468 | path = btrfs_alloc_path(); | ||
1469 | BUG_ON(!path); | ||
1470 | ret = btrfs_insert_extent_backref(trans, extent_root, path, | ||
1471 | ins->objectid, root_objectid, | ||
1472 | ref_generation, owner, owner_offset); | ||
1299 | 1473 | ||
1300 | BUG_ON(ret); | 1474 | BUG_ON(ret); |
1475 | btrfs_free_path(path); | ||
1301 | finish_current_insert(trans, extent_root); | 1476 | finish_current_insert(trans, extent_root); |
1302 | pending_ret = del_pending_extents(trans, extent_root); | 1477 | pending_ret = del_pending_extents(trans, extent_root); |
1303 | 1478 | ||
@@ -1321,15 +1496,43 @@ update_block: | |||
1321 | */ | 1496 | */ |
1322 | struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | 1497 | struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, |
1323 | struct btrfs_root *root, | 1498 | struct btrfs_root *root, |
1324 | u32 blocksize, u64 hint, | 1499 | u32 blocksize, |
1500 | u64 root_objectid, u64 hint, | ||
1501 | u64 empty_size) | ||
1502 | { | ||
1503 | u64 ref_generation; | ||
1504 | |||
1505 | if (root->ref_cows) | ||
1506 | ref_generation = trans->transid; | ||
1507 | else | ||
1508 | ref_generation = 0; | ||
1509 | |||
1510 | |||
1511 | return __btrfs_alloc_free_block(trans, root, blocksize, root_objectid, | ||
1512 | ref_generation, 0, 0, hint, empty_size); | ||
1513 | } | ||
1514 | |||
1515 | /* | ||
1516 | * helper function to allocate a block for a given tree | ||
1517 | * returns the tree buffer or NULL. | ||
1518 | */ | ||
1519 | struct extent_buffer *__btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | ||
1520 | struct btrfs_root *root, | ||
1521 | u32 blocksize, | ||
1522 | u64 root_objectid, | ||
1523 | u64 ref_generation, | ||
1524 | u64 first_objectid, | ||
1525 | int level, | ||
1526 | u64 hint, | ||
1325 | u64 empty_size) | 1527 | u64 empty_size) |
1326 | { | 1528 | { |
1327 | struct btrfs_key ins; | 1529 | struct btrfs_key ins; |
1328 | int ret; | 1530 | int ret; |
1329 | struct extent_buffer *buf; | 1531 | struct extent_buffer *buf; |
1330 | 1532 | ||
1331 | ret = btrfs_alloc_extent(trans, root, root->root_key.objectid, | 1533 | ret = btrfs_alloc_extent(trans, root, blocksize, |
1332 | blocksize, empty_size, hint, | 1534 | root_objectid, ref_generation, |
1535 | first_objectid, level, empty_size, hint, | ||
1333 | (u64)-1, &ins, 0); | 1536 | (u64)-1, &ins, 0); |
1334 | if (ret) { | 1537 | if (ret) { |
1335 | BUG_ON(ret > 0); | 1538 | BUG_ON(ret > 0); |
@@ -1337,7 +1540,9 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | |||
1337 | } | 1540 | } |
1338 | buf = btrfs_find_create_tree_block(root, ins.objectid, blocksize); | 1541 | buf = btrfs_find_create_tree_block(root, ins.objectid, blocksize); |
1339 | if (!buf) { | 1542 | if (!buf) { |
1340 | btrfs_free_extent(trans, root, ins.objectid, blocksize, 0); | 1543 | btrfs_free_extent(trans, root, ins.objectid, blocksize, |
1544 | root->root_key.objectid, ref_generation, | ||
1545 | 0, 0, 0); | ||
1341 | return ERR_PTR(-ENOMEM); | 1546 | return ERR_PTR(-ENOMEM); |
1342 | } | 1547 | } |
1343 | btrfs_set_buffer_uptodate(buf); | 1548 | btrfs_set_buffer_uptodate(buf); |
@@ -1355,6 +1560,8 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | |||
1355 | static int drop_leaf_ref(struct btrfs_trans_handle *trans, | 1560 | static int drop_leaf_ref(struct btrfs_trans_handle *trans, |
1356 | struct btrfs_root *root, struct extent_buffer *leaf) | 1561 | struct btrfs_root *root, struct extent_buffer *leaf) |
1357 | { | 1562 | { |
1563 | u64 leaf_owner; | ||
1564 | u64 leaf_generation; | ||
1358 | struct btrfs_key key; | 1565 | struct btrfs_key key; |
1359 | struct btrfs_file_extent_item *fi; | 1566 | struct btrfs_file_extent_item *fi; |
1360 | int i; | 1567 | int i; |
@@ -1363,6 +1570,9 @@ static int drop_leaf_ref(struct btrfs_trans_handle *trans, | |||
1363 | 1570 | ||
1364 | BUG_ON(!btrfs_is_leaf(leaf)); | 1571 | BUG_ON(!btrfs_is_leaf(leaf)); |
1365 | nritems = btrfs_header_nritems(leaf); | 1572 | nritems = btrfs_header_nritems(leaf); |
1573 | leaf_owner = btrfs_header_owner(leaf); | ||
1574 | leaf_generation = btrfs_header_generation(leaf); | ||
1575 | |||
1366 | for (i = 0; i < nritems; i++) { | 1576 | for (i = 0; i < nritems; i++) { |
1367 | u64 disk_bytenr; | 1577 | u64 disk_bytenr; |
1368 | 1578 | ||
@@ -1381,7 +1591,9 @@ static int drop_leaf_ref(struct btrfs_trans_handle *trans, | |||
1381 | if (disk_bytenr == 0) | 1591 | if (disk_bytenr == 0) |
1382 | continue; | 1592 | continue; |
1383 | ret = btrfs_free_extent(trans, root, disk_bytenr, | 1593 | ret = btrfs_free_extent(trans, root, disk_bytenr, |
1384 | btrfs_file_extent_disk_num_bytes(leaf, fi), 0); | 1594 | btrfs_file_extent_disk_num_bytes(leaf, fi), |
1595 | leaf_owner, leaf_generation, | ||
1596 | key.objectid, key.offset, 0); | ||
1385 | BUG_ON(ret); | 1597 | BUG_ON(ret); |
1386 | } | 1598 | } |
1387 | return 0; | 1599 | return 0; |
@@ -1423,9 +1635,12 @@ static void reada_walk_down(struct btrfs_root *root, | |||
1423 | static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | 1635 | static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root |
1424 | *root, struct btrfs_path *path, int *level) | 1636 | *root, struct btrfs_path *path, int *level) |
1425 | { | 1637 | { |
1638 | u64 root_owner; | ||
1639 | u64 root_gen; | ||
1640 | u64 bytenr; | ||
1426 | struct extent_buffer *next; | 1641 | struct extent_buffer *next; |
1427 | struct extent_buffer *cur; | 1642 | struct extent_buffer *cur; |
1428 | u64 bytenr; | 1643 | struct extent_buffer *parent; |
1429 | u32 blocksize; | 1644 | u32 blocksize; |
1430 | int ret; | 1645 | int ret; |
1431 | u32 refs; | 1646 | u32 refs; |
@@ -1466,9 +1681,13 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1466 | ret = lookup_extent_ref(trans, root, bytenr, blocksize, &refs); | 1681 | ret = lookup_extent_ref(trans, root, bytenr, blocksize, &refs); |
1467 | BUG_ON(ret); | 1682 | BUG_ON(ret); |
1468 | if (refs != 1) { | 1683 | if (refs != 1) { |
1684 | parent = path->nodes[*level]; | ||
1685 | root_owner = btrfs_header_owner(parent); | ||
1686 | root_gen = btrfs_header_generation(parent); | ||
1469 | path->slots[*level]++; | 1687 | path->slots[*level]++; |
1470 | ret = btrfs_free_extent(trans, root, bytenr, | 1688 | ret = btrfs_free_extent(trans, root, bytenr, |
1471 | blocksize, 1); | 1689 | blocksize, root_owner, |
1690 | root_gen, 0, 0, 1); | ||
1472 | BUG_ON(ret); | 1691 | BUG_ON(ret); |
1473 | continue; | 1692 | continue; |
1474 | } | 1693 | } |
@@ -1484,10 +1703,16 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1484 | blocksize, &refs); | 1703 | blocksize, &refs); |
1485 | BUG_ON(ret); | 1704 | BUG_ON(ret); |
1486 | if (refs != 1) { | 1705 | if (refs != 1) { |
1706 | parent = path->nodes[*level]; | ||
1707 | root_owner = btrfs_header_owner(parent); | ||
1708 | root_gen = btrfs_header_generation(parent); | ||
1709 | |||
1487 | path->slots[*level]++; | 1710 | path->slots[*level]++; |
1488 | free_extent_buffer(next); | 1711 | free_extent_buffer(next); |
1489 | ret = btrfs_free_extent(trans, root, | 1712 | ret = btrfs_free_extent(trans, root, bytenr, |
1490 | bytenr, blocksize, 1); | 1713 | blocksize, |
1714 | root_owner, | ||
1715 | root_gen, 0, 0, 1); | ||
1491 | BUG_ON(ret); | 1716 | BUG_ON(ret); |
1492 | continue; | 1717 | continue; |
1493 | } | 1718 | } |
@@ -1502,8 +1727,19 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1502 | out: | 1727 | out: |
1503 | WARN_ON(*level < 0); | 1728 | WARN_ON(*level < 0); |
1504 | WARN_ON(*level >= BTRFS_MAX_LEVEL); | 1729 | WARN_ON(*level >= BTRFS_MAX_LEVEL); |
1730 | |||
1731 | if (path->nodes[*level] == root->node) { | ||
1732 | root_owner = root->root_key.objectid; | ||
1733 | parent = path->nodes[*level]; | ||
1734 | } else { | ||
1735 | parent = path->nodes[*level + 1]; | ||
1736 | root_owner = btrfs_header_owner(parent); | ||
1737 | } | ||
1738 | |||
1739 | root_gen = btrfs_header_generation(parent); | ||
1505 | ret = btrfs_free_extent(trans, root, path->nodes[*level]->start, | 1740 | ret = btrfs_free_extent(trans, root, path->nodes[*level]->start, |
1506 | path->nodes[*level]->len, 1); | 1741 | path->nodes[*level]->len, |
1742 | root_owner, root_gen, 0, 0, 1); | ||
1507 | free_extent_buffer(path->nodes[*level]); | 1743 | free_extent_buffer(path->nodes[*level]); |
1508 | path->nodes[*level] = NULL; | 1744 | path->nodes[*level] = NULL; |
1509 | *level += 1; | 1745 | *level += 1; |
@@ -1519,10 +1755,12 @@ out: | |||
1519 | static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root | 1755 | static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root |
1520 | *root, struct btrfs_path *path, int *level) | 1756 | *root, struct btrfs_path *path, int *level) |
1521 | { | 1757 | { |
1758 | u64 root_owner; | ||
1759 | u64 root_gen; | ||
1760 | struct btrfs_root_item *root_item = &root->root_item; | ||
1522 | int i; | 1761 | int i; |
1523 | int slot; | 1762 | int slot; |
1524 | int ret; | 1763 | int ret; |
1525 | struct btrfs_root_item *root_item = &root->root_item; | ||
1526 | 1764 | ||
1527 | for(i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) { | 1765 | for(i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) { |
1528 | slot = path->slots[i]; | 1766 | slot = path->slots[i]; |
@@ -1539,9 +1777,20 @@ static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1539 | root_item->drop_level = i; | 1777 | root_item->drop_level = i; |
1540 | return 0; | 1778 | return 0; |
1541 | } else { | 1779 | } else { |
1780 | if (path->nodes[*level] == root->node) { | ||
1781 | root_owner = root->root_key.objectid; | ||
1782 | root_gen = | ||
1783 | btrfs_header_generation(path->nodes[*level]); | ||
1784 | } else { | ||
1785 | struct extent_buffer *node; | ||
1786 | node = path->nodes[*level + 1]; | ||
1787 | root_owner = btrfs_header_owner(node); | ||
1788 | root_gen = btrfs_header_generation(node); | ||
1789 | } | ||
1542 | ret = btrfs_free_extent(trans, root, | 1790 | ret = btrfs_free_extent(trans, root, |
1543 | path->nodes[*level]->start, | 1791 | path->nodes[*level]->start, |
1544 | path->nodes[*level]->len, 1); | 1792 | path->nodes[*level]->len, |
1793 | root_owner, root_gen, 0, 0, 1); | ||
1545 | BUG_ON(ret); | 1794 | BUG_ON(ret); |
1546 | free_extent_buffer(path->nodes[*level]); | 1795 | free_extent_buffer(path->nodes[*level]); |
1547 | path->nodes[*level] = NULL; | 1796 | path->nodes[*level] = NULL; |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index b0d637787264..5b1f90f06e03 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -496,7 +496,10 @@ next_slot: | |||
496 | sizeof(old)); | 496 | sizeof(old)); |
497 | if (disk_bytenr != 0) { | 497 | if (disk_bytenr != 0) { |
498 | ret = btrfs_inc_extent_ref(trans, root, | 498 | ret = btrfs_inc_extent_ref(trans, root, |
499 | disk_bytenr, disk_num_bytes); | 499 | disk_bytenr, disk_num_bytes, |
500 | root->root_key.objectid, | ||
501 | trans->transid, | ||
502 | key.objectid, end); | ||
500 | BUG_ON(ret); | 503 | BUG_ON(ret); |
501 | } | 504 | } |
502 | } | 505 | } |
@@ -541,6 +544,14 @@ next_slot: | |||
541 | u64 disk_bytenr = 0; | 544 | u64 disk_bytenr = 0; |
542 | u64 disk_num_bytes = 0; | 545 | u64 disk_num_bytes = 0; |
543 | u64 extent_num_bytes = 0; | 546 | u64 extent_num_bytes = 0; |
547 | u64 root_gen; | ||
548 | |||
549 | if (leaf != root->node) { | ||
550 | root_gen = | ||
551 | btrfs_header_generation(path->nodes[1]); | ||
552 | } else { | ||
553 | root_gen = btrfs_header_generation(leaf); | ||
554 | } | ||
544 | if (found_extent) { | 555 | if (found_extent) { |
545 | disk_bytenr = | 556 | disk_bytenr = |
546 | btrfs_file_extent_disk_bytenr(leaf, | 557 | btrfs_file_extent_disk_bytenr(leaf, |
@@ -562,8 +573,11 @@ next_slot: | |||
562 | if (found_extent && disk_bytenr != 0) { | 573 | if (found_extent && disk_bytenr != 0) { |
563 | inode->i_blocks -= extent_num_bytes >> 9; | 574 | inode->i_blocks -= extent_num_bytes >> 9; |
564 | ret = btrfs_free_extent(trans, root, | 575 | ret = btrfs_free_extent(trans, root, |
565 | disk_bytenr, | 576 | disk_bytenr, |
566 | disk_num_bytes, 0); | 577 | disk_num_bytes, |
578 | root->root_key.objectid, | ||
579 | root_gen, inode->i_ino, | ||
580 | key.offset, 0); | ||
567 | } | 581 | } |
568 | 582 | ||
569 | BUG_ON(ret); | 583 | BUG_ON(ret); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index d0af0807d9f8..bb70db0c9df4 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -93,7 +93,9 @@ static int run_delalloc_range(struct inode *inode, u64 start, u64 end) | |||
93 | if (alloc_hint == EXTENT_MAP_INLINE) | 93 | if (alloc_hint == EXTENT_MAP_INLINE) |
94 | goto out; | 94 | goto out; |
95 | 95 | ||
96 | ret = btrfs_alloc_extent(trans, root, inode->i_ino, num_bytes, 0, | 96 | ret = btrfs_alloc_extent(trans, root, num_bytes, |
97 | root->root_key.objectid, trans->transid, | ||
98 | inode->i_ino, start, 0, | ||
97 | alloc_hint, (u64)-1, &ins, 1); | 99 | alloc_hint, (u64)-1, &ins, 1); |
98 | if (ret) { | 100 | if (ret) { |
99 | WARN_ON(1); | 101 | WARN_ON(1); |
@@ -560,6 +562,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | |||
560 | u64 extent_start = 0; | 562 | u64 extent_start = 0; |
561 | u64 extent_num_bytes = 0; | 563 | u64 extent_num_bytes = 0; |
562 | u64 item_end = 0; | 564 | u64 item_end = 0; |
565 | u64 root_gen = 0; | ||
563 | int found_extent; | 566 | int found_extent; |
564 | int del_item; | 567 | int del_item; |
565 | int extent_type = -1; | 568 | int extent_type = -1; |
@@ -670,6 +673,15 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | |||
670 | found_extent = 1; | 673 | found_extent = 1; |
671 | inode->i_blocks -= num_dec; | 674 | inode->i_blocks -= num_dec; |
672 | } | 675 | } |
676 | if (leaf == root->node) { | ||
677 | root_gen = | ||
678 | btrfs_header_generation(leaf); | ||
679 | } else { | ||
680 | struct extent_buffer *parent; | ||
681 | parent = path->nodes[1]; | ||
682 | root_gen = | ||
683 | btrfs_header_generation(parent); | ||
684 | } | ||
673 | } | 685 | } |
674 | } else if (extent_type == BTRFS_FILE_EXTENT_INLINE && | 686 | } else if (extent_type == BTRFS_FILE_EXTENT_INLINE && |
675 | !del_item) { | 687 | !del_item) { |
@@ -690,7 +702,10 @@ delete: | |||
690 | btrfs_release_path(root, path); | 702 | btrfs_release_path(root, path); |
691 | if (found_extent) { | 703 | if (found_extent) { |
692 | ret = btrfs_free_extent(trans, root, extent_start, | 704 | ret = btrfs_free_extent(trans, root, extent_start, |
693 | extent_num_bytes, 0); | 705 | extent_num_bytes, |
706 | root->root_key.objectid, | ||
707 | root_gen, inode->i_ino, | ||
708 | found_key.offset, 0); | ||
694 | BUG_ON(ret); | 709 | BUG_ON(ret); |
695 | } | 710 | } |
696 | } | 711 | } |
@@ -1900,7 +1915,14 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen) | |||
1900 | trans = btrfs_start_transaction(root, 1); | 1915 | trans = btrfs_start_transaction(root, 1); |
1901 | BUG_ON(!trans); | 1916 | BUG_ON(!trans); |
1902 | 1917 | ||
1903 | leaf = btrfs_alloc_free_block(trans, root, root->leafsize, 0, 0); | 1918 | ret = btrfs_find_free_objectid(trans, root->fs_info->tree_root, |
1919 | 0, &objectid); | ||
1920 | if (ret) | ||
1921 | goto fail; | ||
1922 | |||
1923 | leaf = __btrfs_alloc_free_block(trans, root, root->leafsize, | ||
1924 | objectid, trans->transid, 0, 0, | ||
1925 | 0, 0); | ||
1904 | if (IS_ERR(leaf)) | 1926 | if (IS_ERR(leaf)) |
1905 | return PTR_ERR(leaf); | 1927 | return PTR_ERR(leaf); |
1906 | 1928 | ||
@@ -1908,7 +1930,8 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen) | |||
1908 | btrfs_set_header_level(leaf, 0); | 1930 | btrfs_set_header_level(leaf, 0); |
1909 | btrfs_set_header_bytenr(leaf, leaf->start); | 1931 | btrfs_set_header_bytenr(leaf, leaf->start); |
1910 | btrfs_set_header_generation(leaf, trans->transid); | 1932 | btrfs_set_header_generation(leaf, trans->transid); |
1911 | btrfs_set_header_owner(leaf, root->root_key.objectid); | 1933 | btrfs_set_header_owner(leaf, objectid); |
1934 | |||
1912 | write_extent_buffer(leaf, root->fs_info->fsid, | 1935 | write_extent_buffer(leaf, root->fs_info->fsid, |
1913 | (unsigned long)btrfs_header_fsid(leaf), | 1936 | (unsigned long)btrfs_header_fsid(leaf), |
1914 | BTRFS_FSID_SIZE); | 1937 | BTRFS_FSID_SIZE); |
@@ -1933,11 +1956,6 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen) | |||
1933 | free_extent_buffer(leaf); | 1956 | free_extent_buffer(leaf); |
1934 | leaf = NULL; | 1957 | leaf = NULL; |
1935 | 1958 | ||
1936 | ret = btrfs_find_free_objectid(trans, root->fs_info->tree_root, | ||
1937 | 0, &objectid); | ||
1938 | if (ret) | ||
1939 | goto fail; | ||
1940 | |||
1941 | btrfs_set_root_dirid(&root_item, new_dirid); | 1959 | btrfs_set_root_dirid(&root_item, new_dirid); |
1942 | 1960 | ||
1943 | key.objectid = objectid; | 1961 | key.objectid = objectid; |
@@ -2056,7 +2074,7 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen) | |||
2056 | if (ret) | 2074 | if (ret) |
2057 | goto fail; | 2075 | goto fail; |
2058 | 2076 | ||
2059 | ret = btrfs_inc_root_ref(trans, root); | 2077 | ret = btrfs_inc_root_ref(trans, root, objectid); |
2060 | if (ret) | 2078 | if (ret) |
2061 | goto fail; | 2079 | goto fail; |
2062 | fail: | 2080 | fail: |
diff --git a/fs/btrfs/print-tree.c b/fs/btrfs/print-tree.c index 030324febf6c..da0b4dcf3617 100644 --- a/fs/btrfs/print-tree.c +++ b/fs/btrfs/print-tree.c | |||
@@ -33,6 +33,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) | |||
33 | struct btrfs_file_extent_item *fi; | 33 | struct btrfs_file_extent_item *fi; |
34 | struct btrfs_key key; | 34 | struct btrfs_key key; |
35 | struct btrfs_key found_key; | 35 | struct btrfs_key found_key; |
36 | struct btrfs_extent_ref *ref; | ||
36 | u32 type; | 37 | u32 type; |
37 | 38 | ||
38 | printk("leaf %llu total ptrs %d free space %d\n", | 39 | printk("leaf %llu total ptrs %d free space %d\n", |
@@ -73,6 +74,15 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) | |||
73 | printk("\t\textent data refs %u\n", | 74 | printk("\t\textent data refs %u\n", |
74 | btrfs_extent_refs(l, ei)); | 75 | btrfs_extent_refs(l, ei)); |
75 | break; | 76 | break; |
77 | case BTRFS_EXTENT_REF_KEY: | ||
78 | ref = btrfs_item_ptr(l, i, struct btrfs_extent_ref); | ||
79 | printk("\t\textent back ref root %llu gen %llu " | ||
80 | "owner %llu offset %llu\n", | ||
81 | (unsigned long long)btrfs_ref_root(l, ref), | ||
82 | (unsigned long long)btrfs_ref_generation(l, ref), | ||
83 | (unsigned long long)btrfs_ref_objectid(l, ref), | ||
84 | (unsigned long long)btrfs_ref_offset(l, ref)); | ||
85 | break; | ||
76 | 86 | ||
77 | case BTRFS_EXTENT_DATA_KEY: | 87 | case BTRFS_EXTENT_DATA_KEY: |
78 | fi = btrfs_item_ptr(l, i, | 88 | fi = btrfs_item_ptr(l, i, |
diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c index 3994795edfeb..5c58630dce03 100644 --- a/fs/btrfs/tree-defrag.c +++ b/fs/btrfs/tree-defrag.c | |||
@@ -78,6 +78,8 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans, | |||
78 | break; | 78 | break; |
79 | 79 | ||
80 | if (*level == 1) { | 80 | if (*level == 1) { |
81 | WARN_ON(btrfs_header_generation(path->nodes[*level]) != | ||
82 | trans->transid); | ||
81 | ret = btrfs_realloc_node(trans, root, | 83 | ret = btrfs_realloc_node(trans, root, |
82 | path->nodes[*level], | 84 | path->nodes[*level], |
83 | path->slots[*level], | 85 | path->slots[*level], |