diff options
Diffstat (limited to 'fs/btrfs/backref.c')
-rw-r--r-- | fs/btrfs/backref.c | 63 |
1 files changed, 38 insertions, 25 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index 33cba1abf8b6..523d2dba7745 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c | |||
@@ -40,12 +40,14 @@ static int check_extent_in_eb(const struct btrfs_key *key, | |||
40 | const struct extent_buffer *eb, | 40 | const struct extent_buffer *eb, |
41 | const struct btrfs_file_extent_item *fi, | 41 | const struct btrfs_file_extent_item *fi, |
42 | u64 extent_item_pos, | 42 | u64 extent_item_pos, |
43 | struct extent_inode_elem **eie) | 43 | struct extent_inode_elem **eie, |
44 | bool ignore_offset) | ||
44 | { | 45 | { |
45 | u64 offset = 0; | 46 | u64 offset = 0; |
46 | struct extent_inode_elem *e; | 47 | struct extent_inode_elem *e; |
47 | 48 | ||
48 | if (!btrfs_file_extent_compression(eb, fi) && | 49 | if (!ignore_offset && |
50 | !btrfs_file_extent_compression(eb, fi) && | ||
49 | !btrfs_file_extent_encryption(eb, fi) && | 51 | !btrfs_file_extent_encryption(eb, fi) && |
50 | !btrfs_file_extent_other_encoding(eb, fi)) { | 52 | !btrfs_file_extent_other_encoding(eb, fi)) { |
51 | u64 data_offset; | 53 | u64 data_offset; |
@@ -84,7 +86,8 @@ static void free_inode_elem_list(struct extent_inode_elem *eie) | |||
84 | 86 | ||
85 | static int find_extent_in_eb(const struct extent_buffer *eb, | 87 | static int find_extent_in_eb(const struct extent_buffer *eb, |
86 | u64 wanted_disk_byte, u64 extent_item_pos, | 88 | u64 wanted_disk_byte, u64 extent_item_pos, |
87 | struct extent_inode_elem **eie) | 89 | struct extent_inode_elem **eie, |
90 | bool ignore_offset) | ||
88 | { | 91 | { |
89 | u64 disk_byte; | 92 | u64 disk_byte; |
90 | struct btrfs_key key; | 93 | struct btrfs_key key; |
@@ -113,7 +116,7 @@ static int find_extent_in_eb(const struct extent_buffer *eb, | |||
113 | if (disk_byte != wanted_disk_byte) | 116 | if (disk_byte != wanted_disk_byte) |
114 | continue; | 117 | continue; |
115 | 118 | ||
116 | ret = check_extent_in_eb(&key, eb, fi, extent_item_pos, eie); | 119 | ret = check_extent_in_eb(&key, eb, fi, extent_item_pos, eie, ignore_offset); |
117 | if (ret < 0) | 120 | if (ret < 0) |
118 | return ret; | 121 | return ret; |
119 | } | 122 | } |
@@ -419,7 +422,7 @@ static int add_indirect_ref(const struct btrfs_fs_info *fs_info, | |||
419 | static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path, | 422 | static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path, |
420 | struct ulist *parents, struct prelim_ref *ref, | 423 | struct ulist *parents, struct prelim_ref *ref, |
421 | int level, u64 time_seq, const u64 *extent_item_pos, | 424 | int level, u64 time_seq, const u64 *extent_item_pos, |
422 | u64 total_refs) | 425 | u64 total_refs, bool ignore_offset) |
423 | { | 426 | { |
424 | int ret = 0; | 427 | int ret = 0; |
425 | int slot; | 428 | int slot; |
@@ -472,7 +475,7 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path, | |||
472 | if (extent_item_pos) { | 475 | if (extent_item_pos) { |
473 | ret = check_extent_in_eb(&key, eb, fi, | 476 | ret = check_extent_in_eb(&key, eb, fi, |
474 | *extent_item_pos, | 477 | *extent_item_pos, |
475 | &eie); | 478 | &eie, ignore_offset); |
476 | if (ret < 0) | 479 | if (ret < 0) |
477 | break; | 480 | break; |
478 | } | 481 | } |
@@ -510,7 +513,8 @@ next: | |||
510 | static int resolve_indirect_ref(struct btrfs_fs_info *fs_info, | 513 | static int resolve_indirect_ref(struct btrfs_fs_info *fs_info, |
511 | struct btrfs_path *path, u64 time_seq, | 514 | struct btrfs_path *path, u64 time_seq, |
512 | struct prelim_ref *ref, struct ulist *parents, | 515 | struct prelim_ref *ref, struct ulist *parents, |
513 | const u64 *extent_item_pos, u64 total_refs) | 516 | const u64 *extent_item_pos, u64 total_refs, |
517 | bool ignore_offset) | ||
514 | { | 518 | { |
515 | struct btrfs_root *root; | 519 | struct btrfs_root *root; |
516 | struct btrfs_key root_key; | 520 | struct btrfs_key root_key; |
@@ -581,7 +585,7 @@ static int resolve_indirect_ref(struct btrfs_fs_info *fs_info, | |||
581 | } | 585 | } |
582 | 586 | ||
583 | ret = add_all_parents(root, path, parents, ref, level, time_seq, | 587 | ret = add_all_parents(root, path, parents, ref, level, time_seq, |
584 | extent_item_pos, total_refs); | 588 | extent_item_pos, total_refs, ignore_offset); |
585 | out: | 589 | out: |
586 | path->lowest_level = 0; | 590 | path->lowest_level = 0; |
587 | btrfs_release_path(path); | 591 | btrfs_release_path(path); |
@@ -616,7 +620,7 @@ static int resolve_indirect_refs(struct btrfs_fs_info *fs_info, | |||
616 | struct btrfs_path *path, u64 time_seq, | 620 | struct btrfs_path *path, u64 time_seq, |
617 | struct preftrees *preftrees, | 621 | struct preftrees *preftrees, |
618 | const u64 *extent_item_pos, u64 total_refs, | 622 | const u64 *extent_item_pos, u64 total_refs, |
619 | struct share_check *sc) | 623 | struct share_check *sc, bool ignore_offset) |
620 | { | 624 | { |
621 | int err; | 625 | int err; |
622 | int ret = 0; | 626 | int ret = 0; |
@@ -661,7 +665,7 @@ static int resolve_indirect_refs(struct btrfs_fs_info *fs_info, | |||
661 | } | 665 | } |
662 | err = resolve_indirect_ref(fs_info, path, time_seq, ref, | 666 | err = resolve_indirect_ref(fs_info, path, time_seq, ref, |
663 | parents, extent_item_pos, | 667 | parents, extent_item_pos, |
664 | total_refs); | 668 | total_refs, ignore_offset); |
665 | /* | 669 | /* |
666 | * we can only tolerate ENOENT,otherwise,we should catch error | 670 | * we can only tolerate ENOENT,otherwise,we should catch error |
667 | * and return directly. | 671 | * and return directly. |
@@ -1107,13 +1111,17 @@ static int add_keyed_refs(struct btrfs_fs_info *fs_info, | |||
1107 | * | 1111 | * |
1108 | * Otherwise this returns 0 for success and <0 for an error. | 1112 | * Otherwise this returns 0 for success and <0 for an error. |
1109 | * | 1113 | * |
1114 | * If ignore_offset is set to false, only extent refs whose offsets match | ||
1115 | * extent_item_pos are returned. If true, every extent ref is returned | ||
1116 | * and extent_item_pos is ignored. | ||
1117 | * | ||
1110 | * FIXME some caching might speed things up | 1118 | * FIXME some caching might speed things up |
1111 | */ | 1119 | */ |
1112 | static int find_parent_nodes(struct btrfs_trans_handle *trans, | 1120 | static int find_parent_nodes(struct btrfs_trans_handle *trans, |
1113 | struct btrfs_fs_info *fs_info, u64 bytenr, | 1121 | struct btrfs_fs_info *fs_info, u64 bytenr, |
1114 | u64 time_seq, struct ulist *refs, | 1122 | u64 time_seq, struct ulist *refs, |
1115 | struct ulist *roots, const u64 *extent_item_pos, | 1123 | struct ulist *roots, const u64 *extent_item_pos, |
1116 | struct share_check *sc) | 1124 | struct share_check *sc, bool ignore_offset) |
1117 | { | 1125 | { |
1118 | struct btrfs_key key; | 1126 | struct btrfs_key key; |
1119 | struct btrfs_path *path; | 1127 | struct btrfs_path *path; |
@@ -1235,7 +1243,7 @@ again: | |||
1235 | WARN_ON(!RB_EMPTY_ROOT(&preftrees.indirect_missing_keys.root)); | 1243 | WARN_ON(!RB_EMPTY_ROOT(&preftrees.indirect_missing_keys.root)); |
1236 | 1244 | ||
1237 | ret = resolve_indirect_refs(fs_info, path, time_seq, &preftrees, | 1245 | ret = resolve_indirect_refs(fs_info, path, time_seq, &preftrees, |
1238 | extent_item_pos, total_refs, sc); | 1246 | extent_item_pos, total_refs, sc, ignore_offset); |
1239 | if (ret) | 1247 | if (ret) |
1240 | goto out; | 1248 | goto out; |
1241 | 1249 | ||
@@ -1282,7 +1290,7 @@ again: | |||
1282 | btrfs_tree_read_lock(eb); | 1290 | btrfs_tree_read_lock(eb); |
1283 | btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); | 1291 | btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); |
1284 | ret = find_extent_in_eb(eb, bytenr, | 1292 | ret = find_extent_in_eb(eb, bytenr, |
1285 | *extent_item_pos, &eie); | 1293 | *extent_item_pos, &eie, ignore_offset); |
1286 | btrfs_tree_read_unlock_blocking(eb); | 1294 | btrfs_tree_read_unlock_blocking(eb); |
1287 | free_extent_buffer(eb); | 1295 | free_extent_buffer(eb); |
1288 | if (ret < 0) | 1296 | if (ret < 0) |
@@ -1350,7 +1358,7 @@ static void free_leaf_list(struct ulist *blocks) | |||
1350 | static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans, | 1358 | static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans, |
1351 | struct btrfs_fs_info *fs_info, u64 bytenr, | 1359 | struct btrfs_fs_info *fs_info, u64 bytenr, |
1352 | u64 time_seq, struct ulist **leafs, | 1360 | u64 time_seq, struct ulist **leafs, |
1353 | const u64 *extent_item_pos) | 1361 | const u64 *extent_item_pos, bool ignore_offset) |
1354 | { | 1362 | { |
1355 | int ret; | 1363 | int ret; |
1356 | 1364 | ||
@@ -1359,7 +1367,7 @@ static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans, | |||
1359 | return -ENOMEM; | 1367 | return -ENOMEM; |
1360 | 1368 | ||
1361 | ret = find_parent_nodes(trans, fs_info, bytenr, time_seq, | 1369 | ret = find_parent_nodes(trans, fs_info, bytenr, time_seq, |
1362 | *leafs, NULL, extent_item_pos, NULL); | 1370 | *leafs, NULL, extent_item_pos, NULL, ignore_offset); |
1363 | if (ret < 0 && ret != -ENOENT) { | 1371 | if (ret < 0 && ret != -ENOENT) { |
1364 | free_leaf_list(*leafs); | 1372 | free_leaf_list(*leafs); |
1365 | return ret; | 1373 | return ret; |
@@ -1383,7 +1391,8 @@ static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans, | |||
1383 | */ | 1391 | */ |
1384 | static int btrfs_find_all_roots_safe(struct btrfs_trans_handle *trans, | 1392 | static int btrfs_find_all_roots_safe(struct btrfs_trans_handle *trans, |
1385 | struct btrfs_fs_info *fs_info, u64 bytenr, | 1393 | struct btrfs_fs_info *fs_info, u64 bytenr, |
1386 | u64 time_seq, struct ulist **roots) | 1394 | u64 time_seq, struct ulist **roots, |
1395 | bool ignore_offset) | ||
1387 | { | 1396 | { |
1388 | struct ulist *tmp; | 1397 | struct ulist *tmp; |
1389 | struct ulist_node *node = NULL; | 1398 | struct ulist_node *node = NULL; |
@@ -1402,7 +1411,7 @@ static int btrfs_find_all_roots_safe(struct btrfs_trans_handle *trans, | |||
1402 | ULIST_ITER_INIT(&uiter); | 1411 | ULIST_ITER_INIT(&uiter); |
1403 | while (1) { | 1412 | while (1) { |
1404 | ret = find_parent_nodes(trans, fs_info, bytenr, time_seq, | 1413 | ret = find_parent_nodes(trans, fs_info, bytenr, time_seq, |
1405 | tmp, *roots, NULL, NULL); | 1414 | tmp, *roots, NULL, NULL, ignore_offset); |
1406 | if (ret < 0 && ret != -ENOENT) { | 1415 | if (ret < 0 && ret != -ENOENT) { |
1407 | ulist_free(tmp); | 1416 | ulist_free(tmp); |
1408 | ulist_free(*roots); | 1417 | ulist_free(*roots); |
@@ -1421,14 +1430,15 @@ static int btrfs_find_all_roots_safe(struct btrfs_trans_handle *trans, | |||
1421 | 1430 | ||
1422 | int btrfs_find_all_roots(struct btrfs_trans_handle *trans, | 1431 | int btrfs_find_all_roots(struct btrfs_trans_handle *trans, |
1423 | struct btrfs_fs_info *fs_info, u64 bytenr, | 1432 | struct btrfs_fs_info *fs_info, u64 bytenr, |
1424 | u64 time_seq, struct ulist **roots) | 1433 | u64 time_seq, struct ulist **roots, |
1434 | bool ignore_offset) | ||
1425 | { | 1435 | { |
1426 | int ret; | 1436 | int ret; |
1427 | 1437 | ||
1428 | if (!trans) | 1438 | if (!trans) |
1429 | down_read(&fs_info->commit_root_sem); | 1439 | down_read(&fs_info->commit_root_sem); |
1430 | ret = btrfs_find_all_roots_safe(trans, fs_info, bytenr, | 1440 | ret = btrfs_find_all_roots_safe(trans, fs_info, bytenr, |
1431 | time_seq, roots); | 1441 | time_seq, roots, ignore_offset); |
1432 | if (!trans) | 1442 | if (!trans) |
1433 | up_read(&fs_info->commit_root_sem); | 1443 | up_read(&fs_info->commit_root_sem); |
1434 | return ret; | 1444 | return ret; |
@@ -1483,7 +1493,7 @@ int btrfs_check_shared(struct btrfs_root *root, u64 inum, u64 bytenr) | |||
1483 | ULIST_ITER_INIT(&uiter); | 1493 | ULIST_ITER_INIT(&uiter); |
1484 | while (1) { | 1494 | while (1) { |
1485 | ret = find_parent_nodes(trans, fs_info, bytenr, elem.seq, tmp, | 1495 | ret = find_parent_nodes(trans, fs_info, bytenr, elem.seq, tmp, |
1486 | roots, NULL, &shared); | 1496 | roots, NULL, &shared, false); |
1487 | if (ret == BACKREF_FOUND_SHARED) { | 1497 | if (ret == BACKREF_FOUND_SHARED) { |
1488 | /* this is the only condition under which we return 1 */ | 1498 | /* this is the only condition under which we return 1 */ |
1489 | ret = 1; | 1499 | ret = 1; |
@@ -1877,7 +1887,8 @@ static int iterate_leaf_refs(struct btrfs_fs_info *fs_info, | |||
1877 | int iterate_extent_inodes(struct btrfs_fs_info *fs_info, | 1887 | int iterate_extent_inodes(struct btrfs_fs_info *fs_info, |
1878 | u64 extent_item_objectid, u64 extent_item_pos, | 1888 | u64 extent_item_objectid, u64 extent_item_pos, |
1879 | int search_commit_root, | 1889 | int search_commit_root, |
1880 | iterate_extent_inodes_t *iterate, void *ctx) | 1890 | iterate_extent_inodes_t *iterate, void *ctx, |
1891 | bool ignore_offset) | ||
1881 | { | 1892 | { |
1882 | int ret; | 1893 | int ret; |
1883 | struct btrfs_trans_handle *trans = NULL; | 1894 | struct btrfs_trans_handle *trans = NULL; |
@@ -1903,14 +1914,15 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info, | |||
1903 | 1914 | ||
1904 | ret = btrfs_find_all_leafs(trans, fs_info, extent_item_objectid, | 1915 | ret = btrfs_find_all_leafs(trans, fs_info, extent_item_objectid, |
1905 | tree_mod_seq_elem.seq, &refs, | 1916 | tree_mod_seq_elem.seq, &refs, |
1906 | &extent_item_pos); | 1917 | &extent_item_pos, ignore_offset); |
1907 | if (ret) | 1918 | if (ret) |
1908 | goto out; | 1919 | goto out; |
1909 | 1920 | ||
1910 | ULIST_ITER_INIT(&ref_uiter); | 1921 | ULIST_ITER_INIT(&ref_uiter); |
1911 | while (!ret && (ref_node = ulist_next(refs, &ref_uiter))) { | 1922 | while (!ret && (ref_node = ulist_next(refs, &ref_uiter))) { |
1912 | ret = btrfs_find_all_roots_safe(trans, fs_info, ref_node->val, | 1923 | ret = btrfs_find_all_roots_safe(trans, fs_info, ref_node->val, |
1913 | tree_mod_seq_elem.seq, &roots); | 1924 | tree_mod_seq_elem.seq, &roots, |
1925 | ignore_offset); | ||
1914 | if (ret) | 1926 | if (ret) |
1915 | break; | 1927 | break; |
1916 | ULIST_ITER_INIT(&root_uiter); | 1928 | ULIST_ITER_INIT(&root_uiter); |
@@ -1943,7 +1955,8 @@ out: | |||
1943 | 1955 | ||
1944 | int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info, | 1956 | int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info, |
1945 | struct btrfs_path *path, | 1957 | struct btrfs_path *path, |
1946 | iterate_extent_inodes_t *iterate, void *ctx) | 1958 | iterate_extent_inodes_t *iterate, void *ctx, |
1959 | bool ignore_offset) | ||
1947 | { | 1960 | { |
1948 | int ret; | 1961 | int ret; |
1949 | u64 extent_item_pos; | 1962 | u64 extent_item_pos; |
@@ -1961,7 +1974,7 @@ int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info, | |||
1961 | extent_item_pos = logical - found_key.objectid; | 1974 | extent_item_pos = logical - found_key.objectid; |
1962 | ret = iterate_extent_inodes(fs_info, found_key.objectid, | 1975 | ret = iterate_extent_inodes(fs_info, found_key.objectid, |
1963 | extent_item_pos, search_commit_root, | 1976 | extent_item_pos, search_commit_root, |
1964 | iterate, ctx); | 1977 | iterate, ctx, ignore_offset); |
1965 | 1978 | ||
1966 | return ret; | 1979 | return ret; |
1967 | } | 1980 | } |