const struct extent_buffer *eb,
                              const struct btrfs_file_extent_item *fi,
                              u64 extent_item_pos,
-                             struct extent_inode_elem **eie)
+                             struct extent_inode_elem **eie,
+                             bool ignore_offset)
 {
        u64 offset = 0;
        struct extent_inode_elem *e;
 
-       if (!btrfs_file_extent_compression(eb, fi) &&
+       if (!ignore_offset &&
+           !btrfs_file_extent_compression(eb, fi) &&
            !btrfs_file_extent_encryption(eb, fi) &&
            !btrfs_file_extent_other_encoding(eb, fi)) {
                u64 data_offset;
 
 static int find_extent_in_eb(const struct extent_buffer *eb,
                             u64 wanted_disk_byte, u64 extent_item_pos,
-                            struct extent_inode_elem **eie)
+                            struct extent_inode_elem **eie,
+                            bool ignore_offset)
 {
        u64 disk_byte;
        struct btrfs_key key;
                if (disk_byte != wanted_disk_byte)
                        continue;
 
-               ret = check_extent_in_eb(&key, eb, fi, extent_item_pos, eie);
+               ret = check_extent_in_eb(&key, eb, fi, extent_item_pos, eie, ignore_offset);
                if (ret < 0)
                        return ret;
        }
 static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
                           struct ulist *parents, struct prelim_ref *ref,
                           int level, u64 time_seq, const u64 *extent_item_pos,
-                          u64 total_refs)
+                          u64 total_refs, bool ignore_offset)
 {
        int ret = 0;
        int slot;
                        if (extent_item_pos) {
                                ret = check_extent_in_eb(&key, eb, fi,
                                                *extent_item_pos,
-                                               &eie);
+                                               &eie, ignore_offset);
                                if (ret < 0)
                                        break;
                        }
 static int resolve_indirect_ref(struct btrfs_fs_info *fs_info,
                                struct btrfs_path *path, u64 time_seq,
                                struct prelim_ref *ref, struct ulist *parents,
-                               const u64 *extent_item_pos, u64 total_refs)
+                               const u64 *extent_item_pos, u64 total_refs,
+                               bool ignore_offset)
 {
        struct btrfs_root *root;
        struct btrfs_key root_key;
        }
 
        ret = add_all_parents(root, path, parents, ref, level, time_seq,
-                             extent_item_pos, total_refs);
+                             extent_item_pos, total_refs, ignore_offset);
 out:
        path->lowest_level = 0;
        btrfs_release_path(path);
                                 struct btrfs_path *path, u64 time_seq,
                                 struct preftrees *preftrees,
                                 const u64 *extent_item_pos, u64 total_refs,
-                                struct share_check *sc)
+                                struct share_check *sc, bool ignore_offset)
 {
        int err;
        int ret = 0;
                }
                err = resolve_indirect_ref(fs_info, path, time_seq, ref,
                                           parents, extent_item_pos,
-                                          total_refs);
+                                          total_refs, ignore_offset);
                /*
                 * we can only tolerate ENOENT,otherwise,we should catch error
                 * and return directly.
  *
  * Otherwise this returns 0 for success and <0 for an error.
  *
+ * If ignore_offset is set to false, only extent refs whose offsets match
+ * extent_item_pos are returned.  If true, every extent ref is returned
+ * and extent_item_pos is ignored.
+ *
  * FIXME some caching might speed things up
  */
 static int find_parent_nodes(struct btrfs_trans_handle *trans,
                             struct btrfs_fs_info *fs_info, u64 bytenr,
                             u64 time_seq, struct ulist *refs,
                             struct ulist *roots, const u64 *extent_item_pos,
-                            struct share_check *sc)
+                            struct share_check *sc, bool ignore_offset)
 {
        struct btrfs_key key;
        struct btrfs_path *path;
        WARN_ON(!RB_EMPTY_ROOT(&preftrees.indirect_missing_keys.root));
 
        ret = resolve_indirect_refs(fs_info, path, time_seq, &preftrees,
-                                   extent_item_pos, total_refs, sc);
+                                   extent_item_pos, total_refs, sc, ignore_offset);
        if (ret)
                goto out;
 
                                btrfs_tree_read_lock(eb);
                                btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
                                ret = find_extent_in_eb(eb, bytenr,
-                                                       *extent_item_pos, &eie);
+                                                       *extent_item_pos, &eie, ignore_offset);
                                btrfs_tree_read_unlock_blocking(eb);
                                free_extent_buffer(eb);
                                if (ret < 0)
 static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans,
                                struct btrfs_fs_info *fs_info, u64 bytenr,
                                u64 time_seq, struct ulist **leafs,
-                               const u64 *extent_item_pos)
+                               const u64 *extent_item_pos, bool ignore_offset)
 {
        int ret;
 
                return -ENOMEM;
 
        ret = find_parent_nodes(trans, fs_info, bytenr, time_seq,
-                               *leafs, NULL, extent_item_pos, NULL);
+                               *leafs, NULL, extent_item_pos, NULL, ignore_offset);
        if (ret < 0 && ret != -ENOENT) {
                free_leaf_list(*leafs);
                return ret;
  */
 static int btrfs_find_all_roots_safe(struct btrfs_trans_handle *trans,
                                     struct btrfs_fs_info *fs_info, u64 bytenr,
-                                    u64 time_seq, struct ulist **roots)
+                                    u64 time_seq, struct ulist **roots,
+                                    bool ignore_offset)
 {
        struct ulist *tmp;
        struct ulist_node *node = NULL;
        ULIST_ITER_INIT(&uiter);
        while (1) {
                ret = find_parent_nodes(trans, fs_info, bytenr, time_seq,
-                                       tmp, *roots, NULL, NULL);
+                                       tmp, *roots, NULL, NULL, ignore_offset);
                if (ret < 0 && ret != -ENOENT) {
                        ulist_free(tmp);
                        ulist_free(*roots);
 
 int btrfs_find_all_roots(struct btrfs_trans_handle *trans,
                         struct btrfs_fs_info *fs_info, u64 bytenr,
-                        u64 time_seq, struct ulist **roots)
+                        u64 time_seq, struct ulist **roots,
+                        bool ignore_offset)
 {
        int ret;
 
        if (!trans)
                down_read(&fs_info->commit_root_sem);
        ret = btrfs_find_all_roots_safe(trans, fs_info, bytenr,
-                                       time_seq, roots);
+                                       time_seq, roots, ignore_offset);
        if (!trans)
                up_read(&fs_info->commit_root_sem);
        return ret;
        ULIST_ITER_INIT(&uiter);
        while (1) {
                ret = find_parent_nodes(trans, fs_info, bytenr, elem.seq, tmp,
-                                       roots, NULL, &shared);
+                                       roots, NULL, &shared, false);
                if (ret == BACKREF_FOUND_SHARED) {
                        /* this is the only condition under which we return 1 */
                        ret = 1;
 int iterate_extent_inodes(struct btrfs_fs_info *fs_info,
                                u64 extent_item_objectid, u64 extent_item_pos,
                                int search_commit_root,
-                               iterate_extent_inodes_t *iterate, void *ctx)
+                               iterate_extent_inodes_t *iterate, void *ctx,
+                               bool ignore_offset)
 {
        int ret;
        struct btrfs_trans_handle *trans = NULL;
 
        ret = btrfs_find_all_leafs(trans, fs_info, extent_item_objectid,
                                   tree_mod_seq_elem.seq, &refs,
-                                  &extent_item_pos);
+                                  &extent_item_pos, ignore_offset);
        if (ret)
                goto out;
 
        ULIST_ITER_INIT(&ref_uiter);
        while (!ret && (ref_node = ulist_next(refs, &ref_uiter))) {
                ret = btrfs_find_all_roots_safe(trans, fs_info, ref_node->val,
-                                               tree_mod_seq_elem.seq, &roots);
+                                               tree_mod_seq_elem.seq, &roots,
+                                               ignore_offset);
                if (ret)
                        break;
                ULIST_ITER_INIT(&root_uiter);
 
 int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info,
                                struct btrfs_path *path,
-                               iterate_extent_inodes_t *iterate, void *ctx)
+                               iterate_extent_inodes_t *iterate, void *ctx,
+                               bool ignore_offset)
 {
        int ret;
        u64 extent_item_pos;
        extent_item_pos = logical - found_key.objectid;
        ret = iterate_extent_inodes(fs_info, found_key.objectid,
                                        extent_item_pos, search_commit_root,
-                                       iterate, ctx);
+                                       iterate, ctx, ignore_offset);
 
        return ret;
 }
 
         * we can only call btrfs_qgroup_account_extent() directly to test
         * quota.
         */
-       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots);
+       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots,
+                       false);
        if (ret) {
                ulist_free(old_roots);
                test_msg("Couldn't find old roots: %d\n", ret);
        if (ret)
                return ret;
 
-       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots);
+       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots,
+                       false);
        if (ret) {
                ulist_free(old_roots);
                ulist_free(new_roots);
        old_roots = NULL;
        new_roots = NULL;
 
-       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots);
+       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots,
+                       false);
        if (ret) {
                ulist_free(old_roots);
                test_msg("Couldn't find old roots: %d\n", ret);
        if (ret)
                return -EINVAL;
 
-       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots);
+       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots,
+                       false);
        if (ret) {
                ulist_free(old_roots);
                ulist_free(new_roots);
                return ret;
        }
 
-       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots);
+       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots,
+                       false);
        if (ret) {
                ulist_free(old_roots);
                test_msg("Couldn't find old roots: %d\n", ret);
        if (ret)
                return ret;
 
-       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots);
+       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots,
+                       false);
        if (ret) {
                ulist_free(old_roots);
                ulist_free(new_roots);
                return -EINVAL;
        }
 
-       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots);
+       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots,
+                       false);
        if (ret) {
                ulist_free(old_roots);
                test_msg("Couldn't find old roots: %d\n", ret);
        if (ret)
                return ret;
 
-       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots);
+       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots,
+                       false);
        if (ret) {
                ulist_free(old_roots);
                ulist_free(new_roots);
                return -EINVAL;
        }
 
-       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots);
+       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots,
+                       false);
        if (ret) {
                ulist_free(old_roots);
                test_msg("Couldn't find old roots: %d\n", ret);
        if (ret)
                return ret;
 
-       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots);
+       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots,
+                       false);
        if (ret) {
                ulist_free(old_roots);
                ulist_free(new_roots);