void do_goto_block(int argc, char **argv) { errcode_t retval; blk64_t blk; int level = 0, err; if (common_extent_args_process(argc, argv, 2, 3, "goto_block", "block [level]", 0)) return; if (strtoblk(argv[0], argv[1], &blk)) return; if (argc == 3) { level = parse_ulong(argv[2], argv[0], "level", &err); if (err) return; } retval = ext2fs_extent_goto2(current_handle, level, (blk64_t) blk); if (retval) { com_err(argv[0], retval, "while trying to go to block %llu, level %d", (unsigned long long) blk, level); return; } generic_goto_node(NULL, argc, argv, EXT2_EXTENT_CURRENT); }
/* * Traverse back up to root fixing parents of current node as needed. * * If we changed start of first entry in a node, fix parent index start * and so on. * * Safe to call for any position in node; if not at the first entry, * will simply return. */ errcode_t ext2fs_extent_fix_parents(ext2_extent_handle_t handle) { int retval = 0; int orig_height; blk64_t start; struct extent_path *path; struct ext2fs_extent extent; struct ext2_extent_info info; EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE); if (!(handle->fs->flags & EXT2_FLAG_RW)) return EXT2_ET_RO_FILSYS; if (!handle->path) return EXT2_ET_NO_CURRENT_NODE; path = handle->path + handle->level; if (!path->curr) return EXT2_ET_NO_CURRENT_NODE; retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent); if (retval) goto done; /* modified node's start block */ start = extent.e_lblk; if ((retval = ext2fs_extent_get_info(handle, &info))) return retval; orig_height = info.max_depth - info.curr_level; /* traverse up until index not first, or startblk matches, or top */ while (handle->level > 0 && (path->left == path->entries - 1)) { retval = ext2fs_extent_get(handle, EXT2_EXTENT_UP, &extent); if (retval) goto done; if (extent.e_lblk == start) break; path = handle->path + handle->level; extent.e_len += (extent.e_lblk - start); extent.e_lblk = start; retval = ext2fs_extent_replace(handle, 0, &extent); if (retval) goto done; update_path(handle); } /* put handle back to where we started */ retval = ext2fs_extent_goto2(handle, orig_height, start); done: return retval; }
blk64_t ext2fs_find_inode_goal(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode, blk64_t lblk) { dgrp_t group; __u8 log_flex; struct ext2fs_extent extent; ext2_extent_handle_t handle = NULL; errcode_t err; if (inode == NULL || ext2fs_inode_data_blocks2(fs, inode) == 0) goto no_blocks; if (inode->i_flags & EXT4_INLINE_DATA_FL) goto no_blocks; if (inode->i_flags & EXT4_EXTENTS_FL) { err = ext2fs_extent_open2(fs, ino, inode, &handle); if (err) goto no_blocks; err = ext2fs_extent_goto2(handle, 0, lblk); if (err) goto no_blocks; err = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent); if (err) goto no_blocks; ext2fs_extent_free(handle); return extent.e_pblk + (lblk - extent.e_lblk); } /* block mapped file; see if block zero is mapped? */ if (inode->i_block[0]) return inode->i_block[0]; no_blocks: ext2fs_extent_free(handle); log_flex = fs->super->s_log_groups_per_flex; group = ext2fs_group_of_ino(fs, ino); if (log_flex) group = group & ~((1 << (log_flex)) - 1); return ext2fs_group_first_block2(fs, group); }
errcode_t ext2fs_extent_goto(ext2_extent_handle_t handle, blk64_t blk) { return ext2fs_extent_goto2(handle, 0, blk); }