static int iterate_inode_extrefs(u64 inum, struct btrfs_root *fs_root, struct btrfs_path *path, iterate_irefs_t *iterate, void *ctx) { int ret; int slot; u64 offset = 0; u64 parent; int found = 0; struct extent_buffer *eb; struct btrfs_inode_extref *extref; struct extent_buffer *leaf; u32 item_size; u32 cur_offset; unsigned long ptr; while (1) { ret = btrfs_find_one_extref(fs_root, inum, offset, path, &extref, &offset); if (ret < 0) break; if (ret) { ret = found ? 0 : -ENOENT; break; } ++found; slot = path->slots[0]; eb = path->nodes[0]; /* make sure we can use eb after releasing the path */ atomic_inc(&eb->refs); btrfs_tree_read_lock(eb); btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); btrfs_release_path(path); leaf = path->nodes[0]; item_size = btrfs_item_size_nr(leaf, path->slots[0]); ptr = btrfs_item_ptr_offset(leaf, path->slots[0]); cur_offset = 0; while (cur_offset < item_size) { u32 name_len; extref = (struct btrfs_inode_extref *)(ptr + cur_offset); parent = btrfs_inode_extref_parent(eb, extref); name_len = btrfs_inode_extref_name_len(eb, extref); ret = iterate(parent, name_len, (unsigned long)&extref->name, eb, ctx); if (ret) break; cur_offset += btrfs_inode_extref_name_len(leaf, extref); cur_offset += sizeof(*extref); } btrfs_tree_read_unlock_blocking(eb); free_extent_buffer(eb); offset++; } btrfs_release_path(path); return ret; }
static int iterate_inode_extrefs(u64 inum, struct btrfs_root *fs_root, struct btrfs_path *path, iterate_irefs_t *iterate, void *ctx) { int ret; int slot; u64 offset = 0; u64 parent; int found = 0; struct extent_buffer *eb; struct btrfs_inode_extref *extref; struct extent_buffer *leaf; u32 item_size; u32 cur_offset; unsigned long ptr; while (1) { ret = btrfs_find_one_extref(fs_root, inum, offset, path, &extref, &offset); if (ret < 0) break; if (ret) { ret = found ? 0 : -ENOENT; break; } ++found; slot = path->slots[0]; eb = btrfs_clone_extent_buffer(path->nodes[0]); if (!eb) { ret = -ENOMEM; break; } extent_buffer_get(eb); btrfs_release_path(path); leaf = path->nodes[0]; item_size = btrfs_item_size_nr(leaf, slot); ptr = btrfs_item_ptr_offset(leaf, slot); cur_offset = 0; while (cur_offset < item_size) { u32 name_len; extref = (struct btrfs_inode_extref *)(ptr + cur_offset); parent = btrfs_inode_extref_parent(eb, extref); name_len = btrfs_inode_extref_name_len(eb, extref); ret = iterate(parent, name_len, (unsigned long)&extref->name, eb, ctx); if (ret) break; cur_offset += btrfs_inode_extref_name_len(leaf, extref); cur_offset += sizeof(*extref); } free_extent_buffer(eb); offset++; } btrfs_release_path(path); return ret; }