summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/backref.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/backref.c')
-rw-r--r--fs/btrfs/backref.c63
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
85static int find_extent_in_eb(const struct extent_buffer *eb, 87static 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,
419static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path, 422static 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:
510static int resolve_indirect_ref(struct btrfs_fs_info *fs_info, 513static 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);
585out: 589out:
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 */
1112static int find_parent_nodes(struct btrfs_trans_handle *trans, 1120static 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)
1350static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans, 1358static 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 */
1384static int btrfs_find_all_roots_safe(struct btrfs_trans_handle *trans, 1392static 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
1422int btrfs_find_all_roots(struct btrfs_trans_handle *trans, 1431int 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,
1877int iterate_extent_inodes(struct btrfs_fs_info *fs_info, 1887int 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
1944int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info, 1956int 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}