Beispiel #1
0
int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info,
				struct btrfs_path *path,
				iterate_extent_inodes_t *iterate, void *ctx)
{
	int ret;
	u64 extent_item_pos;
	u64 flags = 0;
	struct btrfs_key found_key;
	int search_commit_root = path->search_commit_root;

	ret = extent_from_logical(fs_info, logical, path, &found_key, &flags);
	btrfs_release_path(path);
	if (ret < 0)
		return ret;
	if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK)
		return -EINVAL;

	extent_item_pos = logical - found_key.objectid;
	ret = iterate_extent_inodes(fs_info, found_key.objectid,
					extent_item_pos, search_commit_root,
					iterate, ctx);

	return ret;
}
Beispiel #2
0
static int __iter_shared_inline_ref_inodes(struct btrfs_fs_info *fs_info,
					   u64 logical, u64 inum,
					   u64 extent_data_item_offset,
					   u64 extent_offset,
					   struct btrfs_path *path,
					   struct list_head *data_refs,
					   iterate_extent_inodes_t *iterate,
					   void *ctx)
{
	u64 ref_root;
	u32 item_size;
	struct btrfs_key key;
	struct extent_buffer *eb;
	struct btrfs_extent_item *ei;
	struct btrfs_extent_inline_ref *eiref;
	struct __data_ref *ref;
	int ret;
	int type;
	int last;
	unsigned long ptr = 0;

	WARN_ON(!list_empty(data_refs));
	ret = extent_from_logical(fs_info, logical, path, &key);
	if (ret & BTRFS_EXTENT_FLAG_DATA)
		ret = -EIO;
	if (ret < 0)
		goto out;

	eb = path->nodes[0];
	ei = btrfs_item_ptr(eb, path->slots[0], struct btrfs_extent_item);
	item_size = btrfs_item_size_nr(eb, path->slots[0]);

	ret = 0;
	ref_root = 0;
	/*
	 * as done in iterate_extent_inodes, we first build a list of refs to
	 * iterate, then free the path and then iterate them to avoid deadlocks.
	 */
	do {
		last = __get_extent_inline_ref(&ptr, eb, ei, item_size,
						&eiref, &type);
		if (last < 0) {
			ret = last;
			goto out;
		}
		if (type == BTRFS_TREE_BLOCK_REF_KEY ||
		    type == BTRFS_SHARED_BLOCK_REF_KEY) {
			ref_root = btrfs_extent_inline_ref_offset(eb, eiref);
			ret = __data_list_add(data_refs, inum,
						extent_data_item_offset,
						ref_root);
		}
	} while (!ret && !last);

	btrfs_release_path(path);

	if (ref_root == 0) {
		printk(KERN_ERR "btrfs: failed to find tree block ref "
			"for shared data backref %llu\n", logical);
		WARN_ON(1);
		ret = -EIO;
	}

out:
	while (!list_empty(data_refs)) {
		ref = list_first_entry(data_refs, struct __data_ref, list);
		list_del(&ref->list);
		if (!ret)
			ret = iterate(ref->inum, extent_offset +
					ref->extent_data_item_offset,
					ref->root, ctx);
		kfree(ref);
	}

	return ret;
}