diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/btrfs/relocation.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'fs/btrfs/relocation.c')
-rw-r--r-- | fs/btrfs/relocation.c | 275 |
1 files changed, 207 insertions, 68 deletions
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index b37d723b9d4a..5e0a3dc79a45 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #include "locking.h" | 29 | #include "locking.h" |
30 | #include "btrfs_inode.h" | 30 | #include "btrfs_inode.h" |
31 | #include "async-thread.h" | 31 | #include "async-thread.h" |
32 | #include "free-space-cache.h" | ||
33 | #include "inode-map.h" | ||
32 | 34 | ||
33 | /* | 35 | /* |
34 | * backref_node, mapping_node and tree_block start with this | 36 | * backref_node, mapping_node and tree_block start with this |
@@ -178,8 +180,6 @@ struct reloc_control { | |||
178 | u64 search_start; | 180 | u64 search_start; |
179 | u64 extents_found; | 181 | u64 extents_found; |
180 | 182 | ||
181 | int block_rsv_retries; | ||
182 | |||
183 | unsigned int stage:8; | 183 | unsigned int stage:8; |
184 | unsigned int create_reloc_tree:1; | 184 | unsigned int create_reloc_tree:1; |
185 | unsigned int merge_reloc_tree:1; | 185 | unsigned int merge_reloc_tree:1; |
@@ -508,6 +508,7 @@ static int update_backref_cache(struct btrfs_trans_handle *trans, | |||
508 | return 1; | 508 | return 1; |
509 | } | 509 | } |
510 | 510 | ||
511 | |||
511 | static int should_ignore_root(struct btrfs_root *root) | 512 | static int should_ignore_root(struct btrfs_root *root) |
512 | { | 513 | { |
513 | struct btrfs_root *reloc_root; | 514 | struct btrfs_root *reloc_root; |
@@ -530,7 +531,6 @@ static int should_ignore_root(struct btrfs_root *root) | |||
530 | */ | 531 | */ |
531 | return 1; | 532 | return 1; |
532 | } | 533 | } |
533 | |||
534 | /* | 534 | /* |
535 | * find reloc tree by address of tree root | 535 | * find reloc tree by address of tree root |
536 | */ | 536 | */ |
@@ -677,6 +677,8 @@ struct backref_node *build_backref_tree(struct reloc_control *rc, | |||
677 | err = -ENOMEM; | 677 | err = -ENOMEM; |
678 | goto out; | 678 | goto out; |
679 | } | 679 | } |
680 | path1->reada = 1; | ||
681 | path2->reada = 2; | ||
680 | 682 | ||
681 | node = alloc_backref_node(cache); | 683 | node = alloc_backref_node(cache); |
682 | if (!node) { | 684 | if (!node) { |
@@ -710,7 +712,7 @@ again: | |||
710 | WARN_ON(cur->checked); | 712 | WARN_ON(cur->checked); |
711 | if (!list_empty(&cur->upper)) { | 713 | if (!list_empty(&cur->upper)) { |
712 | /* | 714 | /* |
713 | * the backref was added previously when processsing | 715 | * the backref was added previously when processing |
714 | * backref of type BTRFS_TREE_BLOCK_REF_KEY | 716 | * backref of type BTRFS_TREE_BLOCK_REF_KEY |
715 | */ | 717 | */ |
716 | BUG_ON(!list_is_singular(&cur->upper)); | 718 | BUG_ON(!list_is_singular(&cur->upper)); |
@@ -962,7 +964,7 @@ again: | |||
962 | lower = upper; | 964 | lower = upper; |
963 | upper = NULL; | 965 | upper = NULL; |
964 | } | 966 | } |
965 | btrfs_release_path(root, path2); | 967 | btrfs_release_path(path2); |
966 | next: | 968 | next: |
967 | if (ptr < end) { | 969 | if (ptr < end) { |
968 | ptr += btrfs_extent_inline_ref_size(key.type); | 970 | ptr += btrfs_extent_inline_ref_size(key.type); |
@@ -975,7 +977,7 @@ next: | |||
975 | if (ptr >= end) | 977 | if (ptr >= end) |
976 | path1->slots[0]++; | 978 | path1->slots[0]++; |
977 | } | 979 | } |
978 | btrfs_release_path(rc->extent_root, path1); | 980 | btrfs_release_path(path1); |
979 | 981 | ||
980 | cur->checked = 1; | 982 | cur->checked = 1; |
981 | WARN_ON(exist); | 983 | WARN_ON(exist); |
@@ -1158,6 +1160,7 @@ static int clone_backref_node(struct btrfs_trans_handle *trans, | |||
1158 | new_node->bytenr = dest->node->start; | 1160 | new_node->bytenr = dest->node->start; |
1159 | new_node->level = node->level; | 1161 | new_node->level = node->level; |
1160 | new_node->lowest = node->lowest; | 1162 | new_node->lowest = node->lowest; |
1163 | new_node->checked = 1; | ||
1161 | new_node->root = dest; | 1164 | new_node->root = dest; |
1162 | 1165 | ||
1163 | if (!node->lowest) { | 1166 | if (!node->lowest) { |
@@ -1365,7 +1368,7 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans, | |||
1365 | int ret; | 1368 | int ret; |
1366 | 1369 | ||
1367 | if (!root->reloc_root) | 1370 | if (!root->reloc_root) |
1368 | return 0; | 1371 | goto out; |
1369 | 1372 | ||
1370 | reloc_root = root->reloc_root; | 1373 | reloc_root = root->reloc_root; |
1371 | root_item = &reloc_root->root_item; | 1374 | root_item = &reloc_root->root_item; |
@@ -1387,6 +1390,8 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans, | |||
1387 | ret = btrfs_update_root(trans, root->fs_info->tree_root, | 1390 | ret = btrfs_update_root(trans, root->fs_info->tree_root, |
1388 | &reloc_root->root_key, root_item); | 1391 | &reloc_root->root_key, root_item); |
1389 | BUG_ON(ret); | 1392 | BUG_ON(ret); |
1393 | |||
1394 | out: | ||
1390 | return 0; | 1395 | return 0; |
1391 | } | 1396 | } |
1392 | 1397 | ||
@@ -1409,9 +1414,9 @@ again: | |||
1409 | prev = node; | 1414 | prev = node; |
1410 | entry = rb_entry(node, struct btrfs_inode, rb_node); | 1415 | entry = rb_entry(node, struct btrfs_inode, rb_node); |
1411 | 1416 | ||
1412 | if (objectid < entry->vfs_inode.i_ino) | 1417 | if (objectid < btrfs_ino(&entry->vfs_inode)) |
1413 | node = node->rb_left; | 1418 | node = node->rb_left; |
1414 | else if (objectid > entry->vfs_inode.i_ino) | 1419 | else if (objectid > btrfs_ino(&entry->vfs_inode)) |
1415 | node = node->rb_right; | 1420 | node = node->rb_right; |
1416 | else | 1421 | else |
1417 | break; | 1422 | break; |
@@ -1419,7 +1424,7 @@ again: | |||
1419 | if (!node) { | 1424 | if (!node) { |
1420 | while (prev) { | 1425 | while (prev) { |
1421 | entry = rb_entry(prev, struct btrfs_inode, rb_node); | 1426 | entry = rb_entry(prev, struct btrfs_inode, rb_node); |
1422 | if (objectid <= entry->vfs_inode.i_ino) { | 1427 | if (objectid <= btrfs_ino(&entry->vfs_inode)) { |
1423 | node = prev; | 1428 | node = prev; |
1424 | break; | 1429 | break; |
1425 | } | 1430 | } |
@@ -1434,7 +1439,7 @@ again: | |||
1434 | return inode; | 1439 | return inode; |
1435 | } | 1440 | } |
1436 | 1441 | ||
1437 | objectid = entry->vfs_inode.i_ino + 1; | 1442 | objectid = btrfs_ino(&entry->vfs_inode) + 1; |
1438 | if (cond_resched_lock(&root->inode_lock)) | 1443 | if (cond_resched_lock(&root->inode_lock)) |
1439 | goto again; | 1444 | goto again; |
1440 | 1445 | ||
@@ -1470,7 +1475,7 @@ static int get_new_location(struct inode *reloc_inode, u64 *new_bytenr, | |||
1470 | return -ENOMEM; | 1475 | return -ENOMEM; |
1471 | 1476 | ||
1472 | bytenr -= BTRFS_I(reloc_inode)->index_cnt; | 1477 | bytenr -= BTRFS_I(reloc_inode)->index_cnt; |
1473 | ret = btrfs_lookup_file_extent(NULL, root, path, reloc_inode->i_ino, | 1478 | ret = btrfs_lookup_file_extent(NULL, root, path, btrfs_ino(reloc_inode), |
1474 | bytenr, 0); | 1479 | bytenr, 0); |
1475 | if (ret < 0) | 1480 | if (ret < 0) |
1476 | goto out; | 1481 | goto out; |
@@ -1558,11 +1563,11 @@ int replace_file_extents(struct btrfs_trans_handle *trans, | |||
1558 | if (first) { | 1563 | if (first) { |
1559 | inode = find_next_inode(root, key.objectid); | 1564 | inode = find_next_inode(root, key.objectid); |
1560 | first = 0; | 1565 | first = 0; |
1561 | } else if (inode && inode->i_ino < key.objectid) { | 1566 | } else if (inode && btrfs_ino(inode) < key.objectid) { |
1562 | btrfs_add_delayed_iput(inode); | 1567 | btrfs_add_delayed_iput(inode); |
1563 | inode = find_next_inode(root, key.objectid); | 1568 | inode = find_next_inode(root, key.objectid); |
1564 | } | 1569 | } |
1565 | if (inode && inode->i_ino == key.objectid) { | 1570 | if (inode && btrfs_ino(inode) == key.objectid) { |
1566 | end = key.offset + | 1571 | end = key.offset + |
1567 | btrfs_file_extent_num_bytes(leaf, fi); | 1572 | btrfs_file_extent_num_bytes(leaf, fi); |
1568 | WARN_ON(!IS_ALIGNED(key.offset, | 1573 | WARN_ON(!IS_ALIGNED(key.offset, |
@@ -1724,6 +1729,7 @@ again: | |||
1724 | 1729 | ||
1725 | eb = read_tree_block(dest, old_bytenr, blocksize, | 1730 | eb = read_tree_block(dest, old_bytenr, blocksize, |
1726 | old_ptr_gen); | 1731 | old_ptr_gen); |
1732 | BUG_ON(!eb); | ||
1727 | btrfs_tree_lock(eb); | 1733 | btrfs_tree_lock(eb); |
1728 | if (cow) { | 1734 | if (cow) { |
1729 | ret = btrfs_cow_block(trans, dest, eb, parent, | 1735 | ret = btrfs_cow_block(trans, dest, eb, parent, |
@@ -1748,7 +1754,7 @@ again: | |||
1748 | 1754 | ||
1749 | btrfs_node_key_to_cpu(path->nodes[level], &key, | 1755 | btrfs_node_key_to_cpu(path->nodes[level], &key, |
1750 | path->slots[level]); | 1756 | path->slots[level]); |
1751 | btrfs_release_path(src, path); | 1757 | btrfs_release_path(path); |
1752 | 1758 | ||
1753 | path->lowest_level = level; | 1759 | path->lowest_level = level; |
1754 | ret = btrfs_search_slot(trans, src, &key, path, 0, 1); | 1760 | ret = btrfs_search_slot(trans, src, &key, path, 0, 1); |
@@ -1892,6 +1898,7 @@ static int invalidate_extent_cache(struct btrfs_root *root, | |||
1892 | struct inode *inode = NULL; | 1898 | struct inode *inode = NULL; |
1893 | u64 objectid; | 1899 | u64 objectid; |
1894 | u64 start, end; | 1900 | u64 start, end; |
1901 | u64 ino; | ||
1895 | 1902 | ||
1896 | objectid = min_key->objectid; | 1903 | objectid = min_key->objectid; |
1897 | while (1) { | 1904 | while (1) { |
@@ -1904,17 +1911,18 @@ static int invalidate_extent_cache(struct btrfs_root *root, | |||
1904 | inode = find_next_inode(root, objectid); | 1911 | inode = find_next_inode(root, objectid); |
1905 | if (!inode) | 1912 | if (!inode) |
1906 | break; | 1913 | break; |
1914 | ino = btrfs_ino(inode); | ||
1907 | 1915 | ||
1908 | if (inode->i_ino > max_key->objectid) { | 1916 | if (ino > max_key->objectid) { |
1909 | iput(inode); | 1917 | iput(inode); |
1910 | break; | 1918 | break; |
1911 | } | 1919 | } |
1912 | 1920 | ||
1913 | objectid = inode->i_ino + 1; | 1921 | objectid = ino + 1; |
1914 | if (!S_ISREG(inode->i_mode)) | 1922 | if (!S_ISREG(inode->i_mode)) |
1915 | continue; | 1923 | continue; |
1916 | 1924 | ||
1917 | if (unlikely(min_key->objectid == inode->i_ino)) { | 1925 | if (unlikely(min_key->objectid == ino)) { |
1918 | if (min_key->type > BTRFS_EXTENT_DATA_KEY) | 1926 | if (min_key->type > BTRFS_EXTENT_DATA_KEY) |
1919 | continue; | 1927 | continue; |
1920 | if (min_key->type < BTRFS_EXTENT_DATA_KEY) | 1928 | if (min_key->type < BTRFS_EXTENT_DATA_KEY) |
@@ -1927,7 +1935,7 @@ static int invalidate_extent_cache(struct btrfs_root *root, | |||
1927 | start = 0; | 1935 | start = 0; |
1928 | } | 1936 | } |
1929 | 1937 | ||
1930 | if (unlikely(max_key->objectid == inode->i_ino)) { | 1938 | if (unlikely(max_key->objectid == ino)) { |
1931 | if (max_key->type < BTRFS_EXTENT_DATA_KEY) | 1939 | if (max_key->type < BTRFS_EXTENT_DATA_KEY) |
1932 | continue; | 1940 | continue; |
1933 | if (max_key->type > BTRFS_EXTENT_DATA_KEY) { | 1941 | if (max_key->type > BTRFS_EXTENT_DATA_KEY) { |
@@ -1995,6 +2003,7 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc, | |||
1995 | path = btrfs_alloc_path(); | 2003 | path = btrfs_alloc_path(); |
1996 | if (!path) | 2004 | if (!path) |
1997 | return -ENOMEM; | 2005 | return -ENOMEM; |
2006 | path->reada = 1; | ||
1998 | 2007 | ||
1999 | reloc_root = root->reloc_root; | 2008 | reloc_root = root->reloc_root; |
2000 | root_item = &reloc_root->root_item; | 2009 | root_item = &reloc_root->root_item; |
@@ -2029,6 +2038,7 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc, | |||
2029 | 2038 | ||
2030 | while (1) { | 2039 | while (1) { |
2031 | trans = btrfs_start_transaction(root, 0); | 2040 | trans = btrfs_start_transaction(root, 0); |
2041 | BUG_ON(IS_ERR(trans)); | ||
2032 | trans->block_rsv = rc->block_rsv; | 2042 | trans->block_rsv = rc->block_rsv; |
2033 | 2043 | ||
2034 | ret = btrfs_block_rsv_check(trans, root, rc->block_rsv, | 2044 | ret = btrfs_block_rsv_check(trans, root, rc->block_rsv, |
@@ -2133,29 +2143,34 @@ int prepare_to_merge(struct reloc_control *rc, int err) | |||
2133 | LIST_HEAD(reloc_roots); | 2143 | LIST_HEAD(reloc_roots); |
2134 | u64 num_bytes = 0; | 2144 | u64 num_bytes = 0; |
2135 | int ret; | 2145 | int ret; |
2136 | int retries = 0; | ||
2137 | 2146 | ||
2138 | mutex_lock(&root->fs_info->trans_mutex); | 2147 | mutex_lock(&root->fs_info->reloc_mutex); |
2139 | rc->merging_rsv_size += root->nodesize * (BTRFS_MAX_LEVEL - 1) * 2; | 2148 | rc->merging_rsv_size += root->nodesize * (BTRFS_MAX_LEVEL - 1) * 2; |
2140 | rc->merging_rsv_size += rc->nodes_relocated * 2; | 2149 | rc->merging_rsv_size += rc->nodes_relocated * 2; |
2141 | mutex_unlock(&root->fs_info->trans_mutex); | 2150 | mutex_unlock(&root->fs_info->reloc_mutex); |
2151 | |||
2142 | again: | 2152 | again: |
2143 | if (!err) { | 2153 | if (!err) { |
2144 | num_bytes = rc->merging_rsv_size; | 2154 | num_bytes = rc->merging_rsv_size; |
2145 | ret = btrfs_block_rsv_add(NULL, root, rc->block_rsv, | 2155 | ret = btrfs_block_rsv_add(NULL, root, rc->block_rsv, |
2146 | num_bytes, &retries); | 2156 | num_bytes); |
2147 | if (ret) | 2157 | if (ret) |
2148 | err = ret; | 2158 | err = ret; |
2149 | } | 2159 | } |
2150 | 2160 | ||
2151 | trans = btrfs_join_transaction(rc->extent_root, 1); | 2161 | trans = btrfs_join_transaction(rc->extent_root); |
2162 | if (IS_ERR(trans)) { | ||
2163 | if (!err) | ||
2164 | btrfs_block_rsv_release(rc->extent_root, | ||
2165 | rc->block_rsv, num_bytes); | ||
2166 | return PTR_ERR(trans); | ||
2167 | } | ||
2152 | 2168 | ||
2153 | if (!err) { | 2169 | if (!err) { |
2154 | if (num_bytes != rc->merging_rsv_size) { | 2170 | if (num_bytes != rc->merging_rsv_size) { |
2155 | btrfs_end_transaction(trans, rc->extent_root); | 2171 | btrfs_end_transaction(trans, rc->extent_root); |
2156 | btrfs_block_rsv_release(rc->extent_root, | 2172 | btrfs_block_rsv_release(rc->extent_root, |
2157 | rc->block_rsv, num_bytes); | 2173 | rc->block_rsv, num_bytes); |
2158 | retries = 0; | ||
2159 | goto again; | 2174 | goto again; |
2160 | } | 2175 | } |
2161 | } | 2176 | } |
@@ -2202,9 +2217,16 @@ int merge_reloc_roots(struct reloc_control *rc) | |||
2202 | int ret; | 2217 | int ret; |
2203 | again: | 2218 | again: |
2204 | root = rc->extent_root; | 2219 | root = rc->extent_root; |
2205 | mutex_lock(&root->fs_info->trans_mutex); | 2220 | |
2221 | /* | ||
2222 | * this serializes us with btrfs_record_root_in_transaction, | ||
2223 | * we have to make sure nobody is in the middle of | ||
2224 | * adding their roots to the list while we are | ||
2225 | * doing this splice | ||
2226 | */ | ||
2227 | mutex_lock(&root->fs_info->reloc_mutex); | ||
2206 | list_splice_init(&rc->reloc_roots, &reloc_roots); | 2228 | list_splice_init(&rc->reloc_roots, &reloc_roots); |
2207 | mutex_unlock(&root->fs_info->trans_mutex); | 2229 | mutex_unlock(&root->fs_info->reloc_mutex); |
2208 | 2230 | ||
2209 | while (!list_empty(&reloc_roots)) { | 2231 | while (!list_empty(&reloc_roots)) { |
2210 | found = 1; | 2232 | found = 1; |
@@ -2340,7 +2362,7 @@ struct btrfs_root *select_one_root(struct btrfs_trans_handle *trans, | |||
2340 | root = next->root; | 2362 | root = next->root; |
2341 | BUG_ON(!root); | 2363 | BUG_ON(!root); |
2342 | 2364 | ||
2343 | /* no other choice for non-refernce counted tree */ | 2365 | /* no other choice for non-references counted tree */ |
2344 | if (!root->ref_cows) | 2366 | if (!root->ref_cows) |
2345 | return root; | 2367 | return root; |
2346 | 2368 | ||
@@ -2405,15 +2427,13 @@ static int reserve_metadata_space(struct btrfs_trans_handle *trans, | |||
2405 | num_bytes = calcu_metadata_size(rc, node, 1) * 2; | 2427 | num_bytes = calcu_metadata_size(rc, node, 1) * 2; |
2406 | 2428 | ||
2407 | trans->block_rsv = rc->block_rsv; | 2429 | trans->block_rsv = rc->block_rsv; |
2408 | ret = btrfs_block_rsv_add(trans, root, rc->block_rsv, num_bytes, | 2430 | ret = btrfs_block_rsv_add(trans, root, rc->block_rsv, num_bytes); |
2409 | &rc->block_rsv_retries); | ||
2410 | if (ret) { | 2431 | if (ret) { |
2411 | if (ret == -EAGAIN) | 2432 | if (ret == -EAGAIN) |
2412 | rc->commit_transaction = 1; | 2433 | rc->commit_transaction = 1; |
2413 | return ret; | 2434 | return ret; |
2414 | } | 2435 | } |
2415 | 2436 | ||
2416 | rc->block_rsv_retries = 0; | ||
2417 | return 0; | 2437 | return 0; |
2418 | } | 2438 | } |
2419 | 2439 | ||
@@ -2492,7 +2512,7 @@ static int do_relocation(struct btrfs_trans_handle *trans, | |||
2492 | path->locks[upper->level] = 0; | 2512 | path->locks[upper->level] = 0; |
2493 | 2513 | ||
2494 | slot = path->slots[upper->level]; | 2514 | slot = path->slots[upper->level]; |
2495 | btrfs_release_path(NULL, path); | 2515 | btrfs_release_path(path); |
2496 | } else { | 2516 | } else { |
2497 | ret = btrfs_bin_search(upper->eb, key, upper->level, | 2517 | ret = btrfs_bin_search(upper->eb, key, upper->level, |
2498 | &slot); | 2518 | &slot); |
@@ -2510,6 +2530,10 @@ static int do_relocation(struct btrfs_trans_handle *trans, | |||
2510 | blocksize = btrfs_level_size(root, node->level); | 2530 | blocksize = btrfs_level_size(root, node->level); |
2511 | generation = btrfs_node_ptr_generation(upper->eb, slot); | 2531 | generation = btrfs_node_ptr_generation(upper->eb, slot); |
2512 | eb = read_tree_block(root, bytenr, blocksize, generation); | 2532 | eb = read_tree_block(root, bytenr, blocksize, generation); |
2533 | if (!eb) { | ||
2534 | err = -EIO; | ||
2535 | goto next; | ||
2536 | } | ||
2513 | btrfs_tree_lock(eb); | 2537 | btrfs_tree_lock(eb); |
2514 | btrfs_set_lock_blocking(eb); | 2538 | btrfs_set_lock_blocking(eb); |
2515 | 2539 | ||
@@ -2667,6 +2691,7 @@ static int get_tree_block_key(struct reloc_control *rc, | |||
2667 | BUG_ON(block->key_ready); | 2691 | BUG_ON(block->key_ready); |
2668 | eb = read_tree_block(rc->extent_root, block->bytenr, | 2692 | eb = read_tree_block(rc->extent_root, block->bytenr, |
2669 | block->key.objectid, block->key.offset); | 2693 | block->key.objectid, block->key.offset); |
2694 | BUG_ON(!eb); | ||
2670 | WARN_ON(btrfs_header_level(eb) != block->level); | 2695 | WARN_ON(btrfs_header_level(eb) != block->level); |
2671 | if (block->level == 0) | 2696 | if (block->level == 0) |
2672 | btrfs_item_key_to_cpu(eb, &block->key, 0); | 2697 | btrfs_item_key_to_cpu(eb, &block->key, 0); |
@@ -2728,7 +2753,7 @@ static int relocate_tree_block(struct btrfs_trans_handle *trans, | |||
2728 | } else { | 2753 | } else { |
2729 | path->lowest_level = node->level; | 2754 | path->lowest_level = node->level; |
2730 | ret = btrfs_search_slot(trans, root, key, path, 0, 1); | 2755 | ret = btrfs_search_slot(trans, root, key, path, 0, 1); |
2731 | btrfs_release_path(root, path); | 2756 | btrfs_release_path(path); |
2732 | if (ret > 0) | 2757 | if (ret > 0) |
2733 | ret = 0; | 2758 | ret = 0; |
2734 | } | 2759 | } |
@@ -2861,7 +2886,7 @@ int setup_extent_mapping(struct inode *inode, u64 start, u64 end, | |||
2861 | struct extent_map *em; | 2886 | struct extent_map *em; |
2862 | int ret = 0; | 2887 | int ret = 0; |
2863 | 2888 | ||
2864 | em = alloc_extent_map(GFP_NOFS); | 2889 | em = alloc_extent_map(); |
2865 | if (!em) | 2890 | if (!em) |
2866 | return -ENOMEM; | 2891 | return -ENOMEM; |
2867 | 2892 | ||
@@ -3099,6 +3124,8 @@ static int add_tree_block(struct reloc_control *rc, | |||
3099 | BUG_ON(item_size != sizeof(struct btrfs_extent_item_v0)); | 3124 | BUG_ON(item_size != sizeof(struct btrfs_extent_item_v0)); |
3100 | ret = get_ref_objectid_v0(rc, path, extent_key, | 3125 | ret = get_ref_objectid_v0(rc, path, extent_key, |
3101 | &ref_owner, NULL); | 3126 | &ref_owner, NULL); |
3127 | if (ret < 0) | ||
3128 | return ret; | ||
3102 | BUG_ON(ref_owner >= BTRFS_MAX_LEVEL); | 3129 | BUG_ON(ref_owner >= BTRFS_MAX_LEVEL); |
3103 | level = (int)ref_owner; | 3130 | level = (int)ref_owner; |
3104 | /* FIXME: get real generation */ | 3131 | /* FIXME: get real generation */ |
@@ -3108,7 +3135,7 @@ static int add_tree_block(struct reloc_control *rc, | |||
3108 | #endif | 3135 | #endif |
3109 | } | 3136 | } |
3110 | 3137 | ||
3111 | btrfs_release_path(rc->extent_root, path); | 3138 | btrfs_release_path(path); |
3112 | 3139 | ||
3113 | BUG_ON(level == -1); | 3140 | BUG_ON(level == -1); |
3114 | 3141 | ||
@@ -3191,6 +3218,55 @@ static int block_use_full_backref(struct reloc_control *rc, | |||
3191 | return ret; | 3218 | return ret; |
3192 | } | 3219 | } |
3193 | 3220 | ||
3221 | static int delete_block_group_cache(struct btrfs_fs_info *fs_info, | ||
3222 | struct inode *inode, u64 ino) | ||
3223 | { | ||
3224 | struct btrfs_key key; | ||
3225 | struct btrfs_path *path; | ||
3226 | struct btrfs_root *root = fs_info->tree_root; | ||
3227 | struct btrfs_trans_handle *trans; | ||
3228 | unsigned long nr; | ||
3229 | int ret = 0; | ||
3230 | |||
3231 | if (inode) | ||
3232 | goto truncate; | ||
3233 | |||
3234 | key.objectid = ino; | ||
3235 | key.type = BTRFS_INODE_ITEM_KEY; | ||
3236 | key.offset = 0; | ||
3237 | |||
3238 | inode = btrfs_iget(fs_info->sb, &key, root, NULL); | ||
3239 | if (IS_ERR_OR_NULL(inode) || is_bad_inode(inode)) { | ||
3240 | if (inode && !IS_ERR(inode)) | ||
3241 | iput(inode); | ||
3242 | return -ENOENT; | ||
3243 | } | ||
3244 | |||
3245 | truncate: | ||
3246 | path = btrfs_alloc_path(); | ||
3247 | if (!path) { | ||
3248 | ret = -ENOMEM; | ||
3249 | goto out; | ||
3250 | } | ||
3251 | |||
3252 | trans = btrfs_join_transaction(root); | ||
3253 | if (IS_ERR(trans)) { | ||
3254 | btrfs_free_path(path); | ||
3255 | ret = PTR_ERR(trans); | ||
3256 | goto out; | ||
3257 | } | ||
3258 | |||
3259 | ret = btrfs_truncate_free_space_cache(root, trans, path, inode); | ||
3260 | |||
3261 | btrfs_free_path(path); | ||
3262 | nr = trans->blocks_used; | ||
3263 | btrfs_end_transaction(trans, root); | ||
3264 | btrfs_btree_balance_dirty(root, nr); | ||
3265 | out: | ||
3266 | iput(inode); | ||
3267 | return ret; | ||
3268 | } | ||
3269 | |||
3194 | /* | 3270 | /* |
3195 | * helper to add tree blocks for backref of type BTRFS_EXTENT_DATA_REF_KEY | 3271 | * helper to add tree blocks for backref of type BTRFS_EXTENT_DATA_REF_KEY |
3196 | * this function scans fs tree to find blocks reference the data extent | 3272 | * this function scans fs tree to find blocks reference the data extent |
@@ -3217,15 +3293,28 @@ static int find_data_references(struct reloc_control *rc, | |||
3217 | int counted; | 3293 | int counted; |
3218 | int ret; | 3294 | int ret; |
3219 | 3295 | ||
3220 | path = btrfs_alloc_path(); | ||
3221 | if (!path) | ||
3222 | return -ENOMEM; | ||
3223 | |||
3224 | ref_root = btrfs_extent_data_ref_root(leaf, ref); | 3296 | ref_root = btrfs_extent_data_ref_root(leaf, ref); |
3225 | ref_objectid = btrfs_extent_data_ref_objectid(leaf, ref); | 3297 | ref_objectid = btrfs_extent_data_ref_objectid(leaf, ref); |
3226 | ref_offset = btrfs_extent_data_ref_offset(leaf, ref); | 3298 | ref_offset = btrfs_extent_data_ref_offset(leaf, ref); |
3227 | ref_count = btrfs_extent_data_ref_count(leaf, ref); | 3299 | ref_count = btrfs_extent_data_ref_count(leaf, ref); |
3228 | 3300 | ||
3301 | /* | ||
3302 | * This is an extent belonging to the free space cache, lets just delete | ||
3303 | * it and redo the search. | ||
3304 | */ | ||
3305 | if (ref_root == BTRFS_ROOT_TREE_OBJECTID) { | ||
3306 | ret = delete_block_group_cache(rc->extent_root->fs_info, | ||
3307 | NULL, ref_objectid); | ||
3308 | if (ret != -ENOENT) | ||
3309 | return ret; | ||
3310 | ret = 0; | ||
3311 | } | ||
3312 | |||
3313 | path = btrfs_alloc_path(); | ||
3314 | if (!path) | ||
3315 | return -ENOMEM; | ||
3316 | path->reada = 1; | ||
3317 | |||
3229 | root = read_fs_root(rc->extent_root->fs_info, ref_root); | 3318 | root = read_fs_root(rc->extent_root->fs_info, ref_root); |
3230 | if (IS_ERR(root)) { | 3319 | if (IS_ERR(root)) { |
3231 | err = PTR_ERR(root); | 3320 | err = PTR_ERR(root); |
@@ -3433,7 +3522,7 @@ int add_data_references(struct reloc_control *rc, | |||
3433 | } | 3522 | } |
3434 | path->slots[0]++; | 3523 | path->slots[0]++; |
3435 | } | 3524 | } |
3436 | btrfs_release_path(rc->extent_root, path); | 3525 | btrfs_release_path(path); |
3437 | if (err) | 3526 | if (err) |
3438 | free_block_list(blocks); | 3527 | free_block_list(blocks); |
3439 | return err; | 3528 | return err; |
@@ -3496,7 +3585,7 @@ next: | |||
3496 | EXTENT_DIRTY); | 3585 | EXTENT_DIRTY); |
3497 | 3586 | ||
3498 | if (ret == 0 && start <= key.objectid) { | 3587 | if (ret == 0 && start <= key.objectid) { |
3499 | btrfs_release_path(rc->extent_root, path); | 3588 | btrfs_release_path(path); |
3500 | rc->search_start = end + 1; | 3589 | rc->search_start = end + 1; |
3501 | } else { | 3590 | } else { |
3502 | rc->search_start = key.objectid + key.offset; | 3591 | rc->search_start = key.objectid + key.offset; |
@@ -3504,24 +3593,26 @@ next: | |||
3504 | return 0; | 3593 | return 0; |
3505 | } | 3594 | } |
3506 | } | 3595 | } |
3507 | btrfs_release_path(rc->extent_root, path); | 3596 | btrfs_release_path(path); |
3508 | return ret; | 3597 | return ret; |
3509 | } | 3598 | } |
3510 | 3599 | ||
3511 | static void set_reloc_control(struct reloc_control *rc) | 3600 | static void set_reloc_control(struct reloc_control *rc) |
3512 | { | 3601 | { |
3513 | struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; | 3602 | struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; |
3514 | mutex_lock(&fs_info->trans_mutex); | 3603 | |
3604 | mutex_lock(&fs_info->reloc_mutex); | ||
3515 | fs_info->reloc_ctl = rc; | 3605 | fs_info->reloc_ctl = rc; |
3516 | mutex_unlock(&fs_info->trans_mutex); | 3606 | mutex_unlock(&fs_info->reloc_mutex); |
3517 | } | 3607 | } |
3518 | 3608 | ||
3519 | static void unset_reloc_control(struct reloc_control *rc) | 3609 | static void unset_reloc_control(struct reloc_control *rc) |
3520 | { | 3610 | { |
3521 | struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; | 3611 | struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; |
3522 | mutex_lock(&fs_info->trans_mutex); | 3612 | |
3613 | mutex_lock(&fs_info->reloc_mutex); | ||
3523 | fs_info->reloc_ctl = NULL; | 3614 | fs_info->reloc_ctl = NULL; |
3524 | mutex_unlock(&fs_info->trans_mutex); | 3615 | mutex_unlock(&fs_info->reloc_mutex); |
3525 | } | 3616 | } |
3526 | 3617 | ||
3527 | static int check_extent_flags(u64 flags) | 3618 | static int check_extent_flags(u64 flags) |
@@ -3554,8 +3645,7 @@ int prepare_to_relocate(struct reloc_control *rc) | |||
3554 | * is no reservation in transaction handle. | 3645 | * is no reservation in transaction handle. |
3555 | */ | 3646 | */ |
3556 | ret = btrfs_block_rsv_add(NULL, rc->extent_root, rc->block_rsv, | 3647 | ret = btrfs_block_rsv_add(NULL, rc->extent_root, rc->block_rsv, |
3557 | rc->extent_root->nodesize * 256, | 3648 | rc->extent_root->nodesize * 256); |
3558 | &rc->block_rsv_retries); | ||
3559 | if (ret) | 3649 | if (ret) |
3560 | return ret; | 3650 | return ret; |
3561 | 3651 | ||
@@ -3567,12 +3657,12 @@ int prepare_to_relocate(struct reloc_control *rc) | |||
3567 | rc->extents_found = 0; | 3657 | rc->extents_found = 0; |
3568 | rc->nodes_relocated = 0; | 3658 | rc->nodes_relocated = 0; |
3569 | rc->merging_rsv_size = 0; | 3659 | rc->merging_rsv_size = 0; |
3570 | rc->block_rsv_retries = 0; | ||
3571 | 3660 | ||
3572 | rc->create_reloc_tree = 1; | 3661 | rc->create_reloc_tree = 1; |
3573 | set_reloc_control(rc); | 3662 | set_reloc_control(rc); |
3574 | 3663 | ||
3575 | trans = btrfs_join_transaction(rc->extent_root, 1); | 3664 | trans = btrfs_join_transaction(rc->extent_root); |
3665 | BUG_ON(IS_ERR(trans)); | ||
3576 | btrfs_commit_transaction(trans, rc->extent_root); | 3666 | btrfs_commit_transaction(trans, rc->extent_root); |
3577 | return 0; | 3667 | return 0; |
3578 | } | 3668 | } |
@@ -3589,10 +3679,12 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) | |||
3589 | u32 item_size; | 3679 | u32 item_size; |
3590 | int ret; | 3680 | int ret; |
3591 | int err = 0; | 3681 | int err = 0; |
3682 | int progress = 0; | ||
3592 | 3683 | ||
3593 | path = btrfs_alloc_path(); | 3684 | path = btrfs_alloc_path(); |
3594 | if (!path) | 3685 | if (!path) |
3595 | return -ENOMEM; | 3686 | return -ENOMEM; |
3687 | path->reada = 1; | ||
3596 | 3688 | ||
3597 | ret = prepare_to_relocate(rc); | 3689 | ret = prepare_to_relocate(rc); |
3598 | if (ret) { | 3690 | if (ret) { |
@@ -3601,8 +3693,10 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) | |||
3601 | } | 3693 | } |
3602 | 3694 | ||
3603 | while (1) { | 3695 | while (1) { |
3696 | progress++; | ||
3604 | trans = btrfs_start_transaction(rc->extent_root, 0); | 3697 | trans = btrfs_start_transaction(rc->extent_root, 0); |
3605 | 3698 | BUG_ON(IS_ERR(trans)); | |
3699 | restart: | ||
3606 | if (update_backref_cache(trans, &rc->backref_cache)) { | 3700 | if (update_backref_cache(trans, &rc->backref_cache)) { |
3607 | btrfs_end_transaction(trans, rc->extent_root); | 3701 | btrfs_end_transaction(trans, rc->extent_root); |
3608 | continue; | 3702 | continue; |
@@ -3639,7 +3733,7 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) | |||
3639 | flags = BTRFS_EXTENT_FLAG_DATA; | 3733 | flags = BTRFS_EXTENT_FLAG_DATA; |
3640 | 3734 | ||
3641 | if (path_change) { | 3735 | if (path_change) { |
3642 | btrfs_release_path(rc->extent_root, path); | 3736 | btrfs_release_path(path); |
3643 | 3737 | ||
3644 | path->search_commit_root = 1; | 3738 | path->search_commit_root = 1; |
3645 | path->skip_locking = 1; | 3739 | path->skip_locking = 1; |
@@ -3662,7 +3756,7 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) | |||
3662 | (flags & BTRFS_EXTENT_FLAG_DATA)) { | 3756 | (flags & BTRFS_EXTENT_FLAG_DATA)) { |
3663 | ret = add_data_references(rc, &key, path, &blocks); | 3757 | ret = add_data_references(rc, &key, path, &blocks); |
3664 | } else { | 3758 | } else { |
3665 | btrfs_release_path(rc->extent_root, path); | 3759 | btrfs_release_path(path); |
3666 | ret = 0; | 3760 | ret = 0; |
3667 | } | 3761 | } |
3668 | if (ret < 0) { | 3762 | if (ret < 0) { |
@@ -3715,8 +3809,17 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) | |||
3715 | } | 3809 | } |
3716 | } | 3810 | } |
3717 | } | 3811 | } |
3812 | if (trans && progress && err == -ENOSPC) { | ||
3813 | ret = btrfs_force_chunk_alloc(trans, rc->extent_root, | ||
3814 | rc->block_group->flags); | ||
3815 | if (ret == 0) { | ||
3816 | err = 0; | ||
3817 | progress = 0; | ||
3818 | goto restart; | ||
3819 | } | ||
3820 | } | ||
3718 | 3821 | ||
3719 | btrfs_release_path(rc->extent_root, path); | 3822 | btrfs_release_path(path); |
3720 | clear_extent_bits(&rc->processed_blocks, 0, (u64)-1, EXTENT_DIRTY, | 3823 | clear_extent_bits(&rc->processed_blocks, 0, (u64)-1, EXTENT_DIRTY, |
3721 | GFP_NOFS); | 3824 | GFP_NOFS); |
3722 | 3825 | ||
@@ -3748,8 +3851,11 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) | |||
3748 | btrfs_block_rsv_release(rc->extent_root, rc->block_rsv, (u64)-1); | 3851 | btrfs_block_rsv_release(rc->extent_root, rc->block_rsv, (u64)-1); |
3749 | 3852 | ||
3750 | /* get rid of pinned extents */ | 3853 | /* get rid of pinned extents */ |
3751 | trans = btrfs_join_transaction(rc->extent_root, 1); | 3854 | trans = btrfs_join_transaction(rc->extent_root); |
3752 | btrfs_commit_transaction(trans, rc->extent_root); | 3855 | if (IS_ERR(trans)) |
3856 | err = PTR_ERR(trans); | ||
3857 | else | ||
3858 | btrfs_commit_transaction(trans, rc->extent_root); | ||
3753 | out_free: | 3859 | out_free: |
3754 | btrfs_free_block_rsv(rc->extent_root, rc->block_rsv); | 3860 | btrfs_free_block_rsv(rc->extent_root, rc->block_rsv); |
3755 | btrfs_free_path(path); | 3861 | btrfs_free_path(path); |
@@ -3781,7 +3887,7 @@ static int __insert_orphan_inode(struct btrfs_trans_handle *trans, | |||
3781 | btrfs_set_inode_flags(leaf, item, BTRFS_INODE_NOCOMPRESS | | 3887 | btrfs_set_inode_flags(leaf, item, BTRFS_INODE_NOCOMPRESS | |
3782 | BTRFS_INODE_PREALLOC); | 3888 | BTRFS_INODE_PREALLOC); |
3783 | btrfs_mark_buffer_dirty(leaf); | 3889 | btrfs_mark_buffer_dirty(leaf); |
3784 | btrfs_release_path(root, path); | 3890 | btrfs_release_path(path); |
3785 | out: | 3891 | out: |
3786 | btrfs_free_path(path); | 3892 | btrfs_free_path(path); |
3787 | return ret; | 3893 | return ret; |
@@ -3811,7 +3917,7 @@ struct inode *create_reloc_inode(struct btrfs_fs_info *fs_info, | |||
3811 | if (IS_ERR(trans)) | 3917 | if (IS_ERR(trans)) |
3812 | return ERR_CAST(trans); | 3918 | return ERR_CAST(trans); |
3813 | 3919 | ||
3814 | err = btrfs_find_free_objectid(trans, root, objectid, &objectid); | 3920 | err = btrfs_find_free_objectid(root, &objectid); |
3815 | if (err) | 3921 | if (err) |
3816 | goto out; | 3922 | goto out; |
3817 | 3923 | ||
@@ -3849,7 +3955,7 @@ static struct reloc_control *alloc_reloc_control(void) | |||
3849 | INIT_LIST_HEAD(&rc->reloc_roots); | 3955 | INIT_LIST_HEAD(&rc->reloc_roots); |
3850 | backref_cache_init(&rc->backref_cache); | 3956 | backref_cache_init(&rc->backref_cache); |
3851 | mapping_tree_init(&rc->reloc_root_tree); | 3957 | mapping_tree_init(&rc->reloc_root_tree); |
3852 | extent_io_tree_init(&rc->processed_blocks, NULL, GFP_NOFS); | 3958 | extent_io_tree_init(&rc->processed_blocks, NULL); |
3853 | return rc; | 3959 | return rc; |
3854 | } | 3960 | } |
3855 | 3961 | ||
@@ -3860,6 +3966,8 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start) | |||
3860 | { | 3966 | { |
3861 | struct btrfs_fs_info *fs_info = extent_root->fs_info; | 3967 | struct btrfs_fs_info *fs_info = extent_root->fs_info; |
3862 | struct reloc_control *rc; | 3968 | struct reloc_control *rc; |
3969 | struct inode *inode; | ||
3970 | struct btrfs_path *path; | ||
3863 | int ret; | 3971 | int ret; |
3864 | int rw = 0; | 3972 | int rw = 0; |
3865 | int err = 0; | 3973 | int err = 0; |
@@ -3882,6 +3990,26 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start) | |||
3882 | rw = 1; | 3990 | rw = 1; |
3883 | } | 3991 | } |
3884 | 3992 | ||
3993 | path = btrfs_alloc_path(); | ||
3994 | if (!path) { | ||
3995 | err = -ENOMEM; | ||
3996 | goto out; | ||
3997 | } | ||
3998 | |||
3999 | inode = lookup_free_space_inode(fs_info->tree_root, rc->block_group, | ||
4000 | path); | ||
4001 | btrfs_free_path(path); | ||
4002 | |||
4003 | if (!IS_ERR(inode)) | ||
4004 | ret = delete_block_group_cache(fs_info, inode, 0); | ||
4005 | else | ||
4006 | ret = PTR_ERR(inode); | ||
4007 | |||
4008 | if (ret && ret != -ENOENT) { | ||
4009 | err = ret; | ||
4010 | goto out; | ||
4011 | } | ||
4012 | |||
3885 | rc->data_inode = create_reloc_inode(fs_info, rc->block_group); | 4013 | rc->data_inode = create_reloc_inode(fs_info, rc->block_group); |
3886 | if (IS_ERR(rc->data_inode)) { | 4014 | if (IS_ERR(rc->data_inode)) { |
3887 | err = PTR_ERR(rc->data_inode); | 4015 | err = PTR_ERR(rc->data_inode); |
@@ -3945,6 +4073,7 @@ static noinline_for_stack int mark_garbage_root(struct btrfs_root *root) | |||
3945 | int ret; | 4073 | int ret; |
3946 | 4074 | ||
3947 | trans = btrfs_start_transaction(root->fs_info->tree_root, 0); | 4075 | trans = btrfs_start_transaction(root->fs_info->tree_root, 0); |
4076 | BUG_ON(IS_ERR(trans)); | ||
3948 | 4077 | ||
3949 | memset(&root->root_item.drop_progress, 0, | 4078 | memset(&root->root_item.drop_progress, 0, |
3950 | sizeof(root->root_item.drop_progress)); | 4079 | sizeof(root->root_item.drop_progress)); |
@@ -3981,6 +4110,7 @@ int btrfs_recover_relocation(struct btrfs_root *root) | |||
3981 | path = btrfs_alloc_path(); | 4110 | path = btrfs_alloc_path(); |
3982 | if (!path) | 4111 | if (!path) |
3983 | return -ENOMEM; | 4112 | return -ENOMEM; |
4113 | path->reada = -1; | ||
3984 | 4114 | ||
3985 | key.objectid = BTRFS_TREE_RELOC_OBJECTID; | 4115 | key.objectid = BTRFS_TREE_RELOC_OBJECTID; |
3986 | key.type = BTRFS_ROOT_ITEM_KEY; | 4116 | key.type = BTRFS_ROOT_ITEM_KEY; |
@@ -4000,7 +4130,7 @@ int btrfs_recover_relocation(struct btrfs_root *root) | |||
4000 | } | 4130 | } |
4001 | leaf = path->nodes[0]; | 4131 | leaf = path->nodes[0]; |
4002 | btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); | 4132 | btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); |
4003 | btrfs_release_path(root->fs_info->tree_root, path); | 4133 | btrfs_release_path(path); |
4004 | 4134 | ||
4005 | if (key.objectid != BTRFS_TREE_RELOC_OBJECTID || | 4135 | if (key.objectid != BTRFS_TREE_RELOC_OBJECTID || |
4006 | key.type != BTRFS_ROOT_ITEM_KEY) | 4136 | key.type != BTRFS_ROOT_ITEM_KEY) |
@@ -4032,7 +4162,7 @@ int btrfs_recover_relocation(struct btrfs_root *root) | |||
4032 | 4162 | ||
4033 | key.offset--; | 4163 | key.offset--; |
4034 | } | 4164 | } |
4035 | btrfs_release_path(root->fs_info->tree_root, path); | 4165 | btrfs_release_path(path); |
4036 | 4166 | ||
4037 | if (list_empty(&reloc_roots)) | 4167 | if (list_empty(&reloc_roots)) |
4038 | goto out; | 4168 | goto out; |
@@ -4047,7 +4177,12 @@ int btrfs_recover_relocation(struct btrfs_root *root) | |||
4047 | 4177 | ||
4048 | set_reloc_control(rc); | 4178 | set_reloc_control(rc); |
4049 | 4179 | ||
4050 | trans = btrfs_join_transaction(rc->extent_root, 1); | 4180 | trans = btrfs_join_transaction(rc->extent_root); |
4181 | if (IS_ERR(trans)) { | ||
4182 | unset_reloc_control(rc); | ||
4183 | err = PTR_ERR(trans); | ||
4184 | goto out_free; | ||
4185 | } | ||
4051 | 4186 | ||
4052 | rc->merge_reloc_tree = 1; | 4187 | rc->merge_reloc_tree = 1; |
4053 | 4188 | ||
@@ -4076,10 +4211,14 @@ int btrfs_recover_relocation(struct btrfs_root *root) | |||
4076 | 4211 | ||
4077 | unset_reloc_control(rc); | 4212 | unset_reloc_control(rc); |
4078 | 4213 | ||
4079 | trans = btrfs_join_transaction(rc->extent_root, 1); | 4214 | trans = btrfs_join_transaction(rc->extent_root); |
4080 | btrfs_commit_transaction(trans, rc->extent_root); | 4215 | if (IS_ERR(trans)) |
4081 | out: | 4216 | err = PTR_ERR(trans); |
4217 | else | ||
4218 | btrfs_commit_transaction(trans, rc->extent_root); | ||
4219 | out_free: | ||
4082 | kfree(rc); | 4220 | kfree(rc); |
4221 | out: | ||
4083 | while (!list_empty(&reloc_roots)) { | 4222 | while (!list_empty(&reloc_roots)) { |
4084 | reloc_root = list_entry(reloc_roots.next, | 4223 | reloc_root = list_entry(reloc_roots.next, |
4085 | struct btrfs_root, root_list); | 4224 | struct btrfs_root, root_list); |
@@ -4097,7 +4236,7 @@ out: | |||
4097 | if (IS_ERR(fs_root)) | 4236 | if (IS_ERR(fs_root)) |
4098 | err = PTR_ERR(fs_root); | 4237 | err = PTR_ERR(fs_root); |
4099 | else | 4238 | else |
4100 | btrfs_orphan_cleanup(fs_root); | 4239 | err = btrfs_orphan_cleanup(fs_root); |
4101 | } | 4240 | } |
4102 | return err; | 4241 | return err; |
4103 | } | 4242 | } |
@@ -4124,7 +4263,7 @@ int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len) | |||
4124 | 4263 | ||
4125 | disk_bytenr = file_pos + BTRFS_I(inode)->index_cnt; | 4264 | disk_bytenr = file_pos + BTRFS_I(inode)->index_cnt; |
4126 | ret = btrfs_lookup_csums_range(root->fs_info->csum_root, disk_bytenr, | 4265 | ret = btrfs_lookup_csums_range(root->fs_info->csum_root, disk_bytenr, |
4127 | disk_bytenr + len - 1, &list); | 4266 | disk_bytenr + len - 1, &list, 0); |
4128 | 4267 | ||
4129 | while (!list_empty(&list)) { | 4268 | while (!list_empty(&list)) { |
4130 | sums = list_entry(list.next, struct btrfs_ordered_sum, list); | 4269 | sums = list_entry(list.next, struct btrfs_ordered_sum, list); |
@@ -4143,7 +4282,7 @@ int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len) | |||
4143 | btrfs_add_ordered_sum(inode, ordered, sums); | 4282 | btrfs_add_ordered_sum(inode, ordered, sums); |
4144 | } | 4283 | } |
4145 | btrfs_put_ordered_extent(ordered); | 4284 | btrfs_put_ordered_extent(ordered); |
4146 | return 0; | 4285 | return ret; |
4147 | } | 4286 | } |
4148 | 4287 | ||
4149 | void btrfs_reloc_cow_block(struct btrfs_trans_handle *trans, | 4288 | void btrfs_reloc_cow_block(struct btrfs_trans_handle *trans, |