13984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt/*
23984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * extent.c --- routines to implement extents support
33984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
43984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Copyright (C) 2007 Theodore Ts'o.
53984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
63984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * %Begin-Header%
78558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall * This file may be redistributed under the terms of the GNU Library
88558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall * General Public License, version 2.
93984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * %End-Header%
103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */
113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include <stdio.h>
133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include <string.h>
143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#if HAVE_UNISTD_H
153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include <unistd.h>
163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#if HAVE_ERRNO_H
183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include <errno.h>
193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#if HAVE_SYS_STAT_H
213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include <sys/stat.h>
223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#if HAVE_SYS_TYPES_H
243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include <sys/types.h>
253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include "ext2_fs.h"
283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include "ext2fsP.h"
293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include "e2image.h"
303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt/*
323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Definitions to be dropped in lib/ext2fs/ext2fs.h
333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */
343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt/*
363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Private definitions
373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */
383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstruct extent_path {
403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	char		*buf;
413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int		entries;
423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int		max_entries;
433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int		left;
443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int		visit_num;
453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int		flags;
463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	blk64_t		end_blk;
473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	void		*curr;
483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt};
493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstruct ext2_extent_handle {
523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	errcode_t		magic;
533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	ext2_filsys		fs;
543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	ext2_ino_t 		ino;
553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext2_inode	*inode;
563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int			type;
573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int			level;
583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int			max_depth;
593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct extent_path	*path;
603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt};
613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstruct ext2_extent_path {
633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	errcode_t		magic;
643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int			leaf_height;
653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	blk64_t			lblk;
663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt};
673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt/*
693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *  Useful Debugging stuff
703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */
713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG
733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic void dbg_show_header(struct ext3_extent_header *eh)
743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	printf("header: magic=%x entries=%u max=%u depth=%u generation=%u\n",
763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_le16_to_cpu(eh->eh_magic),
773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_le16_to_cpu(eh->eh_entries),
783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_le16_to_cpu(eh->eh_max),
793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_le16_to_cpu(eh->eh_depth),
803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_le32_to_cpu(eh->eh_generation));
813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic void dbg_show_index(struct ext3_extent_idx *ix)
843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	printf("index: block=%u leaf=%u leaf_hi=%u unused=%u\n",
863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_le32_to_cpu(ix->ei_block),
873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_le32_to_cpu(ix->ei_leaf),
883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_le16_to_cpu(ix->ei_leaf_hi),
893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_le16_to_cpu(ix->ei_unused));
903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic void dbg_show_extent(struct ext3_extent *ex)
933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	printf("extent: block=%u-%u len=%u start=%u start_hi=%u\n",
953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_le32_to_cpu(ex->ee_block),
963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_le32_to_cpu(ex->ee_block) +
973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_le16_to_cpu(ex->ee_len) - 1,
983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_le16_to_cpu(ex->ee_len),
993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_le32_to_cpu(ex->ee_start),
1003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_le16_to_cpu(ex->ee_start_hi));
1013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
1023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
1033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic void dbg_print_extent(char *desc, struct ext2fs_extent *extent)
1043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
1053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (desc)
1063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		printf("%s: ", desc);
1073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	printf("extent: lblk %llu--%llu, len %u, pblk %llu, flags: ",
1083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	       extent->e_lblk, extent->e_lblk + extent->e_len - 1,
1093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	       extent->e_len, extent->e_pblk);
1103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (extent->e_flags & EXT2_EXTENT_FLAGS_LEAF)
1113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		fputs("LEAF ", stdout);
1123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (extent->e_flags & EXT2_EXTENT_FLAGS_UNINIT)
1133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		fputs("UNINIT ", stdout);
1143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (extent->e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT)
1153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		fputs("2ND_VISIT ", stdout);
1163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!extent->e_flags)
1173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		fputs("(none)", stdout);
1183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	fputc('\n', stdout);
1193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
1203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
1213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
1223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#else
1233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#define dbg_show_header(eh) do { } while (0)
1243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#define dbg_show_index(ix) do { } while (0)
1253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#define dbg_show_extent(ex) do { } while (0)
1263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#define dbg_print_extent(desc, ex) do { } while (0)
1273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
1283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
1293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt/*
1303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Verify the extent header as being sane
1313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */
1323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidterrcode_t ext2fs_extent_header_verify(void *ptr, int size)
1333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
1343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int eh_max, entry_size;
1353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext3_extent_header *eh = ptr;
1363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
1373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	dbg_show_header(eh);
1383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (ext2fs_le16_to_cpu(eh->eh_magic) != EXT3_EXT_MAGIC)
1393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EXT2_ET_EXTENT_HEADER_BAD;
1403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (ext2fs_le16_to_cpu(eh->eh_entries) > ext2fs_le16_to_cpu(eh->eh_max))
1413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EXT2_ET_EXTENT_HEADER_BAD;
1423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (eh->eh_depth == 0)
1433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		entry_size = sizeof(struct ext3_extent);
1443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	else
1453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		entry_size = sizeof(struct ext3_extent_idx);
1463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
1473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	eh_max = (size - sizeof(*eh)) / entry_size;
1483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* Allow two extent-sized items at the end of the block, for
1493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * ext4_extent_tail with checksum in the future. */
1503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if ((ext2fs_le16_to_cpu(eh->eh_max) > eh_max) ||
1513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	    (ext2fs_le16_to_cpu(eh->eh_max) < (eh_max - 2)))
1523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EXT2_ET_EXTENT_HEADER_BAD;
1533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
1543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return 0;
1553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
1563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
1573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
1583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt/*
1593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Begin functions to handle an inode's extent information
1603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */
1613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtextern void ext2fs_extent_free(ext2_extent_handle_t handle)
1623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
1633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int			i;
1643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
1653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!handle)
1663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
1673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
1683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (handle->inode)
1693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ext2fs_free_mem(&handle->inode);
1703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (handle->path) {
1713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		for (i=1; i <= handle->max_depth; i++) {
1723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (handle->path[i].buf)
1733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				ext2fs_free_mem(&handle->path[i].buf);
1743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
1753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ext2fs_free_mem(&handle->path);
1763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
1773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	ext2fs_free_mem(&handle);
1783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
1793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
1803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtextern errcode_t ext2fs_extent_open(ext2_filsys fs, ext2_ino_t ino,
1813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				    ext2_extent_handle_t *ret_handle)
1823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
1833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return ext2fs_extent_open2(fs, ino, NULL, ret_handle);
1843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
1853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
1863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtextern errcode_t ext2fs_extent_open2(ext2_filsys fs, ext2_ino_t ino,
1873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				    struct ext2_inode *inode,
1883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				    ext2_extent_handle_t *ret_handle)
1893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
1903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext2_extent_handle	*handle;
1913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	errcode_t			retval;
1923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int				i;
1933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext3_extent_header	*eh;
1943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
1953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
1963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
1973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!inode)
1983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if ((ino == 0) || (ino > fs->super->s_inodes_count))
1993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			return EXT2_ET_BAD_INODE_NUM;
2003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_get_mem(sizeof(struct ext2_extent_handle), &handle);
2023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval)
2033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return retval;
2043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	memset(handle, 0, sizeof(struct ext2_extent_handle));
2053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_get_mem(sizeof(struct ext2_inode), &handle->inode);
2073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval)
2083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		goto errout;
2093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	handle->ino = ino;
2113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	handle->fs = fs;
2123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (inode) {
2143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		memcpy(handle->inode, inode, sizeof(struct ext2_inode));
2153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
2163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	else {
2173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_read_inode(fs, ino, handle->inode);
2183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
2193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			goto errout;
2203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
2213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	eh = (struct ext3_extent_header *) &handle->inode->i_block[0];
2233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	for (i=0; i < EXT2_N_BLOCKS; i++)
2253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (handle->inode->i_block[i])
2263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			break;
2273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (i >= EXT2_N_BLOCKS) {
2283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		eh->eh_magic = ext2fs_cpu_to_le16(EXT3_EXT_MAGIC);
2293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		eh->eh_depth = 0;
2303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		eh->eh_entries = 0;
2313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		i = (sizeof(handle->inode->i_block) - sizeof(*eh)) /
2323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			sizeof(struct ext3_extent);
2333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		eh->eh_max = ext2fs_cpu_to_le16(i);
2343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		handle->inode->i_flags |= EXT4_EXTENTS_FL;
2353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
2363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!(handle->inode->i_flags & EXT4_EXTENTS_FL)) {
2383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = EXT2_ET_INODE_NOT_EXTENT;
2393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		goto errout;
2403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
2413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_extent_header_verify(eh, sizeof(handle->inode->i_block));
2433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval)
2443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		goto errout;
2453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	handle->max_depth = ext2fs_le16_to_cpu(eh->eh_depth);
2473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	handle->type = ext2fs_le16_to_cpu(eh->eh_magic);
2483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_get_mem(((handle->max_depth+1) *
2503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				 sizeof(struct extent_path)),
2513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				&handle->path);
2523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	memset(handle->path, 0,
2533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	       (handle->max_depth+1) * sizeof(struct extent_path));
2543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	handle->path[0].buf = (char *) handle->inode->i_block;
2553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	handle->path[0].left = handle->path[0].entries =
2573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ext2fs_le16_to_cpu(eh->eh_entries);
2583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	handle->path[0].max_entries = ext2fs_le16_to_cpu(eh->eh_max);
2593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	handle->path[0].curr = 0;
2603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	handle->path[0].end_blk =
2613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		((((__u64) handle->inode->i_size_high << 32) +
2623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		  handle->inode->i_size + (fs->blocksize - 1))
2633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		 >> EXT2_BLOCK_SIZE_BITS(fs->super));
2643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	handle->path[0].visit_num = 1;
2653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	handle->level = 0;
2663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	handle->magic = EXT2_ET_MAGIC_EXTENT_HANDLE;
2673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	*ret_handle = handle;
2693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return 0;
2703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidterrout:
2723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	ext2fs_extent_free(handle);
2733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return retval;
2743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
2753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt/*
2773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * This function is responsible for (optionally) moving through the
2783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * extent tree and then returning the current extent
2793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */
2803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidterrcode_t ext2fs_extent_get(ext2_extent_handle_t handle,
2813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			    int flags, struct ext2fs_extent *extent)
2823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
2833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct extent_path	*path, *newpath;
2843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext3_extent_header	*eh;
2853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext3_extent_idx		*ix = 0;
2863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext3_extent		*ex;
2873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	errcode_t			retval;
2883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	blk_t				blk;
2893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	blk64_t				end_blk;
2903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int				orig_op, op;
2913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE);
2933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!handle->path)
2953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EXT2_ET_NO_CURRENT_NODE;
2963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	orig_op = op = flags & EXT2_EXTENT_MOVE_MASK;
2983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtretry:
3003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	path = handle->path + handle->level;
3013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if ((orig_op == EXT2_EXTENT_NEXT) ||
3023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	    (orig_op == EXT2_EXTENT_NEXT_LEAF)) {
3033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (handle->level < handle->max_depth) {
3043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			/* interior node */
3053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (path->visit_num == 0) {
3063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				path->visit_num++;
3073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				op = EXT2_EXTENT_DOWN;
3083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			} else if (path->left > 0)
3093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				op = EXT2_EXTENT_NEXT_SIB;
3103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			else if (handle->level > 0)
3113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				op = EXT2_EXTENT_UP;
3123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			else
3133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				return EXT2_ET_EXTENT_NO_NEXT;
3143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		} else {
3153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			/* leaf node */
3163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (path->left > 0)
3173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				op = EXT2_EXTENT_NEXT_SIB;
3183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			else if (handle->level > 0)
3193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				op = EXT2_EXTENT_UP;
3203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			else
3213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				return EXT2_ET_EXTENT_NO_NEXT;
3223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
3233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (op != EXT2_EXTENT_NEXT_SIB) {
3243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG_GET_EXTENT
3253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			printf("<<<< OP = %s\n",
3263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			       (op == EXT2_EXTENT_DOWN) ? "down" :
3273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			       ((op == EXT2_EXTENT_UP) ? "up" : "unknown"));
3283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
3293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
3303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
3313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
3323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if ((orig_op == EXT2_EXTENT_PREV) ||
3333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	    (orig_op == EXT2_EXTENT_PREV_LEAF)) {
3343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (handle->level < handle->max_depth) {
3353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			/* interior node */
3363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (path->visit_num > 0 ) {
3373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				/* path->visit_num = 0; */
3383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				op = EXT2_EXTENT_DOWN_AND_LAST;
3393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			} else if (path->left < path->entries-1)
3403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				op = EXT2_EXTENT_PREV_SIB;
3413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			else if (handle->level > 0)
3423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				op = EXT2_EXTENT_UP;
3433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			else
3443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				return EXT2_ET_EXTENT_NO_PREV;
3453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		} else {
3463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			/* leaf node */
3473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (path->left < path->entries-1)
3483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				op = EXT2_EXTENT_PREV_SIB;
3493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			else if (handle->level > 0)
3503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				op = EXT2_EXTENT_UP;
3513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			else
3523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				return EXT2_ET_EXTENT_NO_PREV;
3533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
3543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (op != EXT2_EXTENT_PREV_SIB) {
3553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG_GET_EXTENT
3563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			printf("<<<< OP = %s\n",
3573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			       (op == EXT2_EXTENT_DOWN_AND_LAST) ? "down/last" :
3583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			       ((op == EXT2_EXTENT_UP) ? "up" : "unknown"));
3593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
3603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
3613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
3623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
3633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (orig_op == EXT2_EXTENT_LAST_LEAF) {
3643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if ((handle->level < handle->max_depth) &&
3653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    (path->left == 0))
3663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			op = EXT2_EXTENT_DOWN;
3673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		else
3683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			op = EXT2_EXTENT_LAST_SIB;
3693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG_GET_EXTENT
3703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		printf("<<<< OP = %s\n",
3713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			   (op == EXT2_EXTENT_DOWN) ? "down" : "last_sib");
3723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
3733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
3743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
3753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	switch (op) {
3763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	case EXT2_EXTENT_CURRENT:
3773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ix = path->curr;
3783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		break;
3793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	case EXT2_EXTENT_ROOT:
3803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		handle->level = 0;
3813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		path = handle->path + handle->level;
3823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	case EXT2_EXTENT_FIRST_SIB:
3833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		path->left = path->entries;
3843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		path->curr = 0;
3853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	case EXT2_EXTENT_NEXT_SIB:
3863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (path->left <= 0)
3873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			return EXT2_ET_EXTENT_NO_NEXT;
3883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (path->curr) {
3893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ix = path->curr;
3903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ix++;
3913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		} else {
3923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			eh = (struct ext3_extent_header *) path->buf;
3933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ix = EXT_FIRST_INDEX(eh);
3943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
3953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		path->left--;
3963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		path->curr = ix;
3973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		path->visit_num = 0;
3983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		break;
3993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	case EXT2_EXTENT_PREV_SIB:
4003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (!path->curr ||
4013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    path->left+1 >= path->entries)
4023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			return EXT2_ET_EXTENT_NO_PREV;
4033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ix = path->curr;
4043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ix--;
4053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		path->curr = ix;
4063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		path->left++;
4073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (handle->level < handle->max_depth)
4083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			path->visit_num = 1;
4093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		break;
4103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	case EXT2_EXTENT_LAST_SIB:
4113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		eh = (struct ext3_extent_header *) path->buf;
4123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		path->curr = EXT_LAST_EXTENT(eh);
4133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ix = path->curr;
4143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		path->left = 0;
4153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		path->visit_num = 0;
4163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		break;
4173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	case EXT2_EXTENT_UP:
4183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (handle->level <= 0)
4193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			return EXT2_ET_EXTENT_NO_UP;
4203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		handle->level--;
4213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		path--;
4223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ix = path->curr;
4233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if ((orig_op == EXT2_EXTENT_PREV) ||
4243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    (orig_op == EXT2_EXTENT_PREV_LEAF))
4253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			path->visit_num = 0;
4263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		break;
4273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	case EXT2_EXTENT_DOWN:
4283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	case EXT2_EXTENT_DOWN_AND_LAST:
4293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (!path->curr ||(handle->level >= handle->max_depth))
4303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			return EXT2_ET_EXTENT_NO_DOWN;
4313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
4323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ix = path->curr;
4333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		newpath = path + 1;
4343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (!newpath->buf) {
4353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			retval = ext2fs_get_mem(handle->fs->blocksize,
4363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt						&newpath->buf);
4373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (retval)
4383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				return retval;
4393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
4403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		blk = ext2fs_le32_to_cpu(ix->ei_leaf) +
4413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			((__u64) ext2fs_le16_to_cpu(ix->ei_leaf_hi) << 32);
4423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if ((handle->fs->flags & EXT2_FLAG_IMAGE_FILE) &&
4433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    (handle->fs->io != handle->fs->image_io))
4443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			memset(newpath->buf, 0, handle->fs->blocksize);
4453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		else {
4463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			retval = io_channel_read_blk(handle->fs->io,
4473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt						     blk, 1, newpath->buf);
4483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (retval)
4493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				return retval;
4503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
4513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		handle->level++;
4523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
4533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		eh = (struct ext3_extent_header *) newpath->buf;
4543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
4553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_extent_header_verify(eh, handle->fs->blocksize);
4563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval) {
4573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			handle->level--;
4583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			return retval;
4593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
4603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
4613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		newpath->left = newpath->entries =
4623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_le16_to_cpu(eh->eh_entries);
4633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		newpath->max_entries = ext2fs_le16_to_cpu(eh->eh_max);
4643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
4653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (path->left > 0) {
4663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ix++;
4673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			newpath->end_blk = ext2fs_le32_to_cpu(ix->ei_block);
4683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		} else
4693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			newpath->end_blk = path->end_blk;
4703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
4713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		path = newpath;
4723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (op == EXT2_EXTENT_DOWN) {
4733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ix = EXT_FIRST_INDEX((struct ext3_extent_header *) eh);
4743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			path->curr = ix;
4753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			path->left = path->entries - 1;
4763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			path->visit_num = 0;
4773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		} else {
4783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ix = EXT_LAST_INDEX((struct ext3_extent_header *) eh);
4793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			path->curr = ix;
4803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			path->left = 0;
4813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (handle->level < handle->max_depth)
4823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				path->visit_num = 1;
4833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
4843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG_GET_EXTENT
4853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		printf("Down to level %d/%d, end_blk=%llu\n",
4863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			   handle->level, handle->max_depth,
4873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			   path->end_blk);
4883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
4893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		break;
4903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	default:
4913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EXT2_ET_OP_NOT_SUPPORTED;
4923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
4933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
4943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!ix)
4953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EXT2_ET_NO_CURRENT_NODE;
4963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
4973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	extent->e_flags = 0;
4983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG_GET_EXTENT
4993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	printf("(Left %d)\n", path->left);
5003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
5013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
5023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (handle->level == handle->max_depth) {
5033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ex = (struct ext3_extent *) ix;
5043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
5053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent->e_pblk = ext2fs_le32_to_cpu(ex->ee_start) +
5063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			((__u64) ext2fs_le16_to_cpu(ex->ee_start_hi) << 32);
5073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent->e_lblk = ext2fs_le32_to_cpu(ex->ee_block);
5083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent->e_len = ext2fs_le16_to_cpu(ex->ee_len);
5093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent->e_flags |= EXT2_EXTENT_FLAGS_LEAF;
5103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (extent->e_len > EXT_INIT_MAX_LEN) {
5113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			extent->e_len -= EXT_INIT_MAX_LEN;
5123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			extent->e_flags |= EXT2_EXTENT_FLAGS_UNINIT;
5133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
5143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	} else {
5153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent->e_pblk = ext2fs_le32_to_cpu(ix->ei_leaf) +
5163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			((__u64) ext2fs_le16_to_cpu(ix->ei_leaf_hi) << 32);
5173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent->e_lblk = ext2fs_le32_to_cpu(ix->ei_block);
5183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (path->left > 0) {
5193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ix++;
5203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			end_blk = ext2fs_le32_to_cpu(ix->ei_block);
5213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		} else
5223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			end_blk = path->end_blk;
5233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
5243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent->e_len = end_blk - extent->e_lblk;
5253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
5263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (path->visit_num)
5273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent->e_flags |= EXT2_EXTENT_FLAGS_SECOND_VISIT;
5283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
5293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (((orig_op == EXT2_EXTENT_NEXT_LEAF) ||
5303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	     (orig_op == EXT2_EXTENT_PREV_LEAF)) &&
5313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	    (handle->level != handle->max_depth))
5323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		goto retry;
5333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
5343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if ((orig_op == EXT2_EXTENT_LAST_LEAF) &&
5353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	    ((handle->level != handle->max_depth) ||
5363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	     (path->left != 0)))
5373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		goto retry;
5383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
5393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return 0;
5403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
5413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
5423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic errcode_t update_path(ext2_extent_handle_t handle)
5433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
5443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	blk64_t				blk;
5453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	errcode_t			retval;
5463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext3_extent_idx		*ix;
5473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
5483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (handle->level == 0) {
5493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_write_inode(handle->fs, handle->ino,
5503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					    handle->inode);
5513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	} else {
5523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ix = handle->path[handle->level - 1].curr;
5533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		blk = ext2fs_le32_to_cpu(ix->ei_leaf) +
5543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			((__u64) ext2fs_le16_to_cpu(ix->ei_leaf_hi) << 32);
5553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
5563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = io_channel_write_blk(handle->fs->io,
5573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				      blk, 1, handle->path[handle->level].buf);
5583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
5593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return retval;
5603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
5613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
5623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#if 0
5633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidterrcode_t ext2fs_extent_save_path(ext2_extent_handle_t handle,
5643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				  ext2_extent_path_t *ret_path)
5653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
5663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	ext2_extent_path_t	save_path;
5673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext2fs_extent	extent;
5683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext2_extent_info	info;
5693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	errcode_t		retval;
5703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
5713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent);
5723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval)
5733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return retval;
5743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
5753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_extent_get_info(handle, &info);
5763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval)
5773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return retval;
5783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
5793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_get_mem(sizeof(struct ext2_extent_path), &save_path);
5803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval)
5813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return retval;
5823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	memset(save_path, 0, sizeof(struct ext2_extent_path));
5833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
5843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	save_path->magic = EXT2_ET_MAGIC_EXTENT_PATH;
5853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	save_path->leaf_height = info.max_depth - info.curr_level - 1;
5863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	save_path->lblk = extent.e_lblk;
5873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
5883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	*ret_path = save_path;
5893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return 0;
5903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
5913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
5923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidterrcode_t ext2fs_extent_free_path(ext2_extent_path_t path)
5933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
5943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	EXT2_CHECK_MAGIC(path, EXT2_ET_MAGIC_EXTENT_PATH);
5953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
5963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	ext2fs_free_mem(&path);
5973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return 0;
5983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
5993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
6003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
6013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt/*
6023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Go to the node at leaf_level which contains logical block blk.
6033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
6043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * leaf_level is height from the leaf node level, i.e.
6053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * leaf_level 0 is at leaf node, leaf_level 1 is 1 above etc.
6063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
6073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * If "blk" has no mapping (hole) then handle is left at last
6083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * extent before blk.
6093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */
6103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic errcode_t extent_goto(ext2_extent_handle_t handle,
6113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			     int leaf_level, blk64_t blk)
6123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
6133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext2fs_extent	extent;
6143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	errcode_t		retval;
6153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
6163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_extent_get(handle, EXT2_EXTENT_ROOT, &extent);
6173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval) {
6183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval == EXT2_ET_EXTENT_NO_NEXT)
6193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			retval = EXT2_ET_EXTENT_NOT_FOUND;
6203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return retval;
6213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
6223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
6233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (leaf_level > handle->max_depth) {
6243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG
6253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		printf("leaf level %d greater than tree depth %d\n",
6263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			leaf_level, handle->max_depth);
6273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
6283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EXT2_ET_OP_NOT_SUPPORTED;
6293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
6303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
6313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG
6323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	printf("goto extent ino %u, level %d, %llu\n", handle->ino,
6333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	       leaf_level, blk);
6343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
6353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
6363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG_GOTO_EXTENTS
6373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	dbg_print_extent("root", &extent);
6383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
6393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	while (1) {
6403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (handle->max_depth - handle->level == leaf_level) {
6413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			/* block is in this &extent */
6423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if ((blk >= extent.e_lblk) &&
6433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			    (blk < extent.e_lblk + extent.e_len))
6443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				return 0;
6453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (blk < extent.e_lblk) {
6463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				retval = ext2fs_extent_get(handle,
6473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt							   EXT2_EXTENT_PREV_SIB,
6483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt							   &extent);
6493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				return EXT2_ET_EXTENT_NOT_FOUND;
6503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			}
6513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			retval = ext2fs_extent_get(handle,
6523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt						   EXT2_EXTENT_NEXT_SIB,
6533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt						   &extent);
6543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (retval == EXT2_ET_EXTENT_NO_NEXT)
6553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				return EXT2_ET_EXTENT_NOT_FOUND;
6563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (retval)
6573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				return retval;
6583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			continue;
6593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
6603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
6613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT_SIB,
6623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					   &extent);
6633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval == EXT2_ET_EXTENT_NO_NEXT)
6643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			goto go_down;
6653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
6663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			return retval;
6673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
6683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG_GOTO_EXTENTS
6693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		dbg_print_extent("next", &extent);
6703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
6713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (blk == extent.e_lblk)
6723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			goto go_down;
6733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (blk > extent.e_lblk)
6743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			continue;
6753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
6763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_extent_get(handle, EXT2_EXTENT_PREV_SIB,
6773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					   &extent);
6783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
6793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			return retval;
6803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
6813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG_GOTO_EXTENTS
6823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		dbg_print_extent("prev", &extent);
6833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
6843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
6853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	go_down:
6863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_extent_get(handle, EXT2_EXTENT_DOWN,
6873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					   &extent);
6883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
6893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			return retval;
6903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
6913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG_GOTO_EXTENTS
6923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		dbg_print_extent("down", &extent);
6933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
6943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
6953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
6963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
6973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidterrcode_t ext2fs_extent_goto(ext2_extent_handle_t handle,
6983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			     blk64_t blk)
6993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
7003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return extent_goto(handle, 0, blk);
7013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
7023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
7033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt/*
7043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Traverse back up to root fixing parents of current node as needed.
7053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
7063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * If we changed start of first entry in a node, fix parent index start
7073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * and so on.
7083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
7093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Safe to call for any position in node; if not at the first entry,
7103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * will  simply return.
7113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */
7123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic errcode_t ext2fs_extent_fix_parents(ext2_extent_handle_t handle)
7133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
7143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int				retval = 0;
7153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	blk64_t				start;
7163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct extent_path		*path;
7173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext2fs_extent		extent;
7183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
7193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE);
7203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
7213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!(handle->fs->flags & EXT2_FLAG_RW))
7223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EXT2_ET_RO_FILSYS;
7233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
7243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!handle->path)
7253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EXT2_ET_NO_CURRENT_NODE;
7263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
7273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	path = handle->path + handle->level;
7283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!path->curr)
7293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EXT2_ET_NO_CURRENT_NODE;
7303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
7313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent);
7323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval)
7333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		goto done;
7343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
7353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* modified node's start block */
7363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	start = extent.e_lblk;
7373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
7383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* traverse up until index not first, or startblk matches, or top */
7393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	while (handle->level > 0 &&
7403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	       (path->left == path->entries - 1)) {
7413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_extent_get(handle, EXT2_EXTENT_UP, &extent);
7423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
7433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			goto done;
7443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (extent.e_lblk == start)
7453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			break;
7463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		path = handle->path + handle->level;
7473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent.e_len += (extent.e_lblk - start);
7483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent.e_lblk = start;
7493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_extent_replace(handle, 0, &extent);
7503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
7513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			goto done;
7523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		update_path(handle);
7533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
7543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
7553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* put handle back to where we started */
7563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_extent_goto(handle, start);
7573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtdone:
7583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return retval;
7593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
7603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
7613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidterrcode_t ext2fs_extent_replace(ext2_extent_handle_t handle,
7623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				int flags EXT2FS_ATTR((unused)),
7633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				struct ext2fs_extent *extent)
7643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
7653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct extent_path		*path;
7663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext3_extent_idx		*ix;
7673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext3_extent		*ex;
7683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
7693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE);
7703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
7713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!(handle->fs->flags & EXT2_FLAG_RW))
7723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EXT2_ET_RO_FILSYS;
7733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
7743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!handle->path)
7753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EXT2_ET_NO_CURRENT_NODE;
7763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
7773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	path = handle->path + handle->level;
7783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!path->curr)
7793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EXT2_ET_NO_CURRENT_NODE;
7803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
7813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG
7823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	printf("extent replace: %u ", handle->ino);
7833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	dbg_print_extent(0, extent);
7843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
7853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
7863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (handle->level == handle->max_depth) {
7873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ex = path->curr;
7883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
7893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ex->ee_block = ext2fs_cpu_to_le32(extent->e_lblk);
7903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ex->ee_start = ext2fs_cpu_to_le32(extent->e_pblk & 0xFFFFFFFF);
7913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ex->ee_start_hi = ext2fs_cpu_to_le16(extent->e_pblk >> 32);
7923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (extent->e_flags & EXT2_EXTENT_FLAGS_UNINIT) {
7933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (extent->e_len > EXT_UNINIT_MAX_LEN)
7943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				return EXT2_ET_EXTENT_INVALID_LENGTH;
7953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ex->ee_len = ext2fs_cpu_to_le16(extent->e_len +
7963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt							EXT_INIT_MAX_LEN);
7973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		} else {
7983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (extent->e_len > EXT_INIT_MAX_LEN)
7993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				return EXT2_ET_EXTENT_INVALID_LENGTH;
8003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ex->ee_len = ext2fs_cpu_to_le16(extent->e_len);
8013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
8023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	} else {
8033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ix = path->curr;
8043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
8053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ix->ei_leaf = ext2fs_cpu_to_le32(extent->e_pblk & 0xFFFFFFFF);
8063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ix->ei_leaf_hi = ext2fs_cpu_to_le16(extent->e_pblk >> 32);
8073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ix->ei_block = ext2fs_cpu_to_le32(extent->e_lblk);
8083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ix->ei_unused = 0;
8093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
8103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	update_path(handle);
8113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return 0;
8123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
8133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
8143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt/*
8153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * allocate a new block, move half the current node to it, and update parent
8163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
8173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * handle will be left pointing at original record.
8183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */
8193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic errcode_t extent_node_split(ext2_extent_handle_t handle)
8203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
8213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	errcode_t			retval = 0;
8223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	blk_t				new_node_pblk;
8233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	blk64_t				new_node_start;
8243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	blk64_t				orig_lblk;
8253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	blk64_t				goal_blk = 0;
8263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int				orig_height;
8273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	char				*block_buf = NULL;
8283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext2fs_extent		extent;
8293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct extent_path		*path, *newpath = 0;
8303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext3_extent_header	*eh, *neweh;
8313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int				tocopy;
8323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int				new_root = 0;
8333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext2_extent_info		info;
8343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
8353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* basic sanity */
8363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE);
8373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
8383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!(handle->fs->flags & EXT2_FLAG_RW))
8393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EXT2_ET_RO_FILSYS;
8403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
8413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!handle->path)
8423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EXT2_ET_NO_CURRENT_NODE;
8433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
8443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG
8453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	printf("splitting node at level %d\n", handle->level);
8463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
8473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent);
8483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval)
8493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		goto done;
8503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
8513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_extent_get_info(handle, &info);
8523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval)
8533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		goto done;
8543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
8553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* save the position we were originally splitting... */
8563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	orig_height = info.max_depth - info.curr_level;
8573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	orig_lblk = extent.e_lblk;
8583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
8593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* Is there room in the parent for a new entry? */
8603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (handle->level &&
8613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			(handle->path[handle->level - 1].entries >=
8623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			 handle->path[handle->level - 1].max_entries)) {
8633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
8643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG
8653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		printf("parent level %d full; splitting it too\n",
8663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt							handle->level - 1);
8673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
8683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		/* split the parent */
8693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_extent_get(handle, EXT2_EXTENT_UP, &extent);
8703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
8713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			goto done;
8723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		goal_blk = extent.e_pblk;
8733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
8743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = extent_node_split(handle);
8753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
8763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			goto done;
8773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
8783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		/* get handle back to our original split position */
8793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = extent_goto(handle, orig_height, orig_lblk);
8803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
8813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			goto done;
8823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
8833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
8843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* At this point, parent should have room for this split */
8853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	path = handle->path + handle->level;
8863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!path->curr)
8873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EXT2_ET_NO_CURRENT_NODE;
8883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
8893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* extent header of the current node we'll split */
8903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	eh = (struct ext3_extent_header *)path->buf;
8913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
8923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* splitting root level means moving them all out */
8933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (handle->level == 0) {
8943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		new_root = 1;
8953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		tocopy = ext2fs_le16_to_cpu(eh->eh_entries);
8963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_get_mem(((handle->max_depth+2) *
8973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					 sizeof(struct extent_path)),
8983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					&newpath);
8993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
9003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			goto done;
9013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		memset(newpath, 0,
9023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		       ((handle->max_depth+2) * sizeof(struct extent_path)));
9033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	} else {
9043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		tocopy = ext2fs_le16_to_cpu(eh->eh_entries) / 2;
9053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
9063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
9073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG
9083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	printf("will copy out %d of %d entries at level %d\n",
9093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				tocopy, ext2fs_le16_to_cpu(eh->eh_entries),
9103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				handle->level);
9113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
9123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
9133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!tocopy) {
9143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG
9153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		printf("Nothing to copy to new block!\n");
9163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
9173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = EXT2_ET_CANT_SPLIT_EXTENT;
9183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		goto done;
9193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
9203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
9213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* first we need a new block, or can do nothing. */
9223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	block_buf = malloc(handle->fs->blocksize);
9233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!block_buf) {
9243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ENOMEM;
9253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		goto done;
9263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
9273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
9283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!goal_blk) {
9293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		dgrp_t	group = ext2fs_group_of_ino(handle->fs, handle->ino);
9303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		__u8	log_flex = handle->fs->super->s_log_groups_per_flex;
9313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
9323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (log_flex)
9333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			group = group & ~((1 << (log_flex)) - 1);
9343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		goal_blk = (group * handle->fs->super->s_blocks_per_group) +
9353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			handle->fs->super->s_first_data_block;
9363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
9373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_alloc_block(handle->fs, (blk_t) goal_blk, block_buf,
9383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				    &new_node_pblk);
9393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval)
9403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		goto done;
9413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
9423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG
9433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	printf("will copy to new node at block %lu\n",
9443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	       (unsigned long) new_node_pblk);
9453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
9463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
9473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* Copy data into new block buffer */
9483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* First the header for the new block... */
9493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	neweh = (struct ext3_extent_header *) block_buf;
9503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	memcpy(neweh, eh, sizeof(struct ext3_extent_header));
9513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	neweh->eh_entries = ext2fs_cpu_to_le16(tocopy);
9523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	neweh->eh_max = ext2fs_cpu_to_le16((handle->fs->blocksize -
9533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			 sizeof(struct ext3_extent_header)) /
9543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				sizeof(struct ext3_extent));
9553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
9563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* then the entries for the new block... */
9573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	memcpy(EXT_FIRST_INDEX(neweh),
9583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		EXT_FIRST_INDEX(eh) +
9593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			(ext2fs_le16_to_cpu(eh->eh_entries) - tocopy),
9603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		sizeof(struct ext3_extent_idx) * tocopy);
9613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
9623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	new_node_start = ext2fs_le32_to_cpu(EXT_FIRST_INDEX(neweh)->ei_block);
9633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
9643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* ...and write the new node block out to disk. */
9653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = io_channel_write_blk(handle->fs->io, new_node_pblk, 1, block_buf);
9663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
9673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval)
9683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		goto done;
9693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
9703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* OK! we've created the new node; now adjust the tree */
9713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
9723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* current path now has fewer active entries, we copied some out */
9733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (handle->level == 0) {
9743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		memcpy(newpath, path,
9753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		       sizeof(struct extent_path) * (handle->max_depth+1));
9763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		handle->path = newpath;
9773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		newpath = path;
9783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		path = handle->path;
9793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		path->entries = 1;
9803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		path->left = path->max_entries - 1;
9813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		handle->max_depth++;
9823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		eh->eh_depth = ext2fs_cpu_to_le16(handle->max_depth);
9833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	} else {
9843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		path->entries -= tocopy;
9853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		path->left -= tocopy;
9863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
9873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
9883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	eh->eh_entries = ext2fs_cpu_to_le16(path->entries);
9893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* this writes out the node, incl. the modified header */
9903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = update_path(handle);
9913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval)
9923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		goto done;
9933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
9943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* now go up and insert/replace index for new node we created */
9953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (new_root) {
9963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_extent_get(handle, EXT2_EXTENT_FIRST_SIB, &extent);
9973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
9983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			goto done;
9993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent.e_lblk = new_node_start;
10013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent.e_pblk = new_node_pblk;
10023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent.e_len = handle->path[0].end_blk - extent.e_lblk;
10033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_extent_replace(handle, 0, &extent);
10043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
10053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			goto done;
10063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	} else {
10073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		__u32 new_node_length;
10083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_extent_get(handle, EXT2_EXTENT_UP, &extent);
10103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		/* will insert after this one; it's length is shorter now */
10113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		new_node_length = new_node_start - extent.e_lblk;
10123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent.e_len -= new_node_length;
10133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_extent_replace(handle, 0, &extent);
10143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
10153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			goto done;
10163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		/* now set up the new extent and insert it */
10183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent.e_lblk = new_node_start;
10193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent.e_pblk = new_node_pblk;
10203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent.e_len = new_node_length;
10213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_extent_insert(handle, EXT2_EXTENT_INSERT_AFTER, &extent);
10223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
10233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			goto done;
10243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
10253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* get handle back to our original position */
10273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = extent_goto(handle, orig_height, orig_lblk);
10283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval)
10293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		goto done;
10303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* new node hooked in, so update inode block count (do this here?) */
10323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	handle->inode->i_blocks += handle->fs->blocksize / 512;
10333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_write_inode(handle->fs, handle->ino,
10343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				    handle->inode);
10353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval)
10363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		goto done;
10373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtdone:
10393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (newpath)
10403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ext2fs_free_mem(&newpath);
10413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	free(block_buf);
10423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return retval;
10443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
10453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidterrcode_t ext2fs_extent_insert(ext2_extent_handle_t handle, int flags,
10473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				      struct ext2fs_extent *extent)
10483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
10493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct extent_path		*path;
10503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext3_extent_idx		*ix;
10513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext3_extent_header	*eh;
10523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	errcode_t			retval;
10533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE);
10553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!(handle->fs->flags & EXT2_FLAG_RW))
10573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EXT2_ET_RO_FILSYS;
10583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!handle->path)
10603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EXT2_ET_NO_CURRENT_NODE;
10613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG
10633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	printf("extent insert: %u ", handle->ino);
10643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	dbg_print_extent(0, extent);
10653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
10663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	path = handle->path + handle->level;
10683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (path->entries >= path->max_entries) {
10703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (flags & EXT2_EXTENT_INSERT_NOSPLIT) {
10713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			return EXT2_ET_CANT_INSERT_EXTENT;
10723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		} else {
10733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG
10743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			printf("node full (level %d) - splitting\n",
10753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				   handle->level);
10763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
10773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			retval = extent_node_split(handle);
10783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (retval)
10793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				return retval;
10803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			path = handle->path + handle->level;
10813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
10823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
10833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	eh = (struct ext3_extent_header *) path->buf;
10853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (path->curr) {
10863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ix = path->curr;
10873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (flags & EXT2_EXTENT_INSERT_AFTER) {
10883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ix++;
10893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			path->left--;
10903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
10913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	} else
10923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ix = EXT_FIRST_INDEX(eh);
10933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	path->curr = ix;
10953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (path->left >= 0)
10973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		memmove(ix + 1, ix,
10983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			(path->left+1) * sizeof(struct ext3_extent_idx));
10993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	path->left++;
11003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	path->entries++;
11013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
11023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	eh = (struct ext3_extent_header *) path->buf;
11033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	eh->eh_entries = ext2fs_cpu_to_le16(path->entries);
11043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
11053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_extent_replace(handle, 0, extent);
11063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval)
11073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		goto errout;
11083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
11093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = update_path(handle);
11103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval)
11113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		goto errout;
11123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
11133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return 0;
11143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
11153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidterrout:
11163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	ext2fs_extent_delete(handle, 0);
11173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return retval;
11183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
11193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
11203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt/*
11213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Sets the physical block for a logical file block in the extent tree.
11223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
11233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * May: map unmapped, unmap mapped, or remap mapped blocks.
11243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
11253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Mapping an unmapped block adds a single-block extent.
11263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
11273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Unmapping first or last block modifies extent in-place
11283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *  - But may need to fix parent's starts too in first-block case
11293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
11303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Mapping any unmapped block requires adding a (single-block) extent
11313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * and inserting into proper point in tree.
11323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
11333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Modifying (unmapping or remapping) a block in the middle
11343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * of an extent requires splitting the extent.
11353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *  - Remapping case requires new single-block extent.
11363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
11373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Remapping first or last block adds an extent.
11383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
11393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * We really need extent adding to be smart about merging.
11403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */
11413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
11423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidterrcode_t ext2fs_extent_set_bmap(ext2_extent_handle_t handle,
11433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				 blk64_t logical, blk64_t physical, int flags)
11443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
11453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	errcode_t		ec, retval = 0;
11463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int			mapped = 1; /* logical is mapped? */
11473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int			orig_height;
11483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int			extent_uninit = 0;
11493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int			prev_uninit = 0;
11503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int			next_uninit = 0;
11513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int			new_uninit = 0;
11523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int			max_len = EXT_INIT_MAX_LEN;
11533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int			has_prev, has_next;
11543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	blk64_t			orig_lblk;
11553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct extent_path	*path;
11563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext2fs_extent	extent, next_extent, prev_extent;
11573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext2fs_extent	newextent;
11583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext2_extent_info	info;
11593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
11603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE);
11613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
11623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG
11633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	printf("set_bmap ino %u log %lld phys %lld flags %d\n",
11643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	       handle->ino, logical, physical, flags);
11653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
11663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
11673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!(handle->fs->flags & EXT2_FLAG_RW))
11683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EXT2_ET_RO_FILSYS;
11693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
11703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!handle->path)
11713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EXT2_ET_NO_CURRENT_NODE;
11723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
11733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	path = handle->path + handle->level;
11743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
11753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (flags & EXT2_EXTENT_SET_BMAP_UNINIT) {
11763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		new_uninit = 1;
11773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		max_len = EXT_UNINIT_MAX_LEN;
11783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
11793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
11803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* if (re)mapping, set up new extent to insert */
11813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (physical) {
11823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		newextent.e_len = 1;
11833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		newextent.e_pblk = physical;
11843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		newextent.e_lblk = logical;
11853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		newextent.e_flags = EXT2_EXTENT_FLAGS_LEAF;
11863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (new_uninit)
11873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			newextent.e_flags |= EXT2_EXTENT_FLAGS_UNINIT;
11883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
11893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
11903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* special case if the extent tree is completely empty */
11913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if ((handle->max_depth == 0) && (path->entries == 0)) {
11923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_extent_insert(handle, 0, &newextent);
11933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return retval;
11943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
11953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
11963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* save our original location in the extent tree */
11973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if ((retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT,
11983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					&extent))) {
11993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval != EXT2_ET_NO_CURRENT_NODE)
12003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			return retval;
12013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		memset(&extent, 0, sizeof(extent));
12023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
12033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if ((retval = ext2fs_extent_get_info(handle, &info)))
12043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return retval;
12053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	orig_height = info.max_depth - info.curr_level;
12063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	orig_lblk = extent.e_lblk;
12073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
12083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* go to the logical spot we want to (re/un)map */
12093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_extent_goto(handle, logical);
12103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval) {
12113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval == EXT2_ET_EXTENT_NOT_FOUND) {
12123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			retval = 0;
12133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			mapped = 0;
12143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (!physical) {
12153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG
12163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				printf("block %llu already unmapped\n",
12173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					logical);
12183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
12193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				goto done;
12203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			}
12213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		} else
12223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			goto done;
12233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
12243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
12253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/*
12263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * This may be the extent *before* the requested logical,
12273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * if it's currently unmapped.
12283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 *
12293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * Get the previous and next leaf extents, if they are present.
12303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 */
12313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent);
12323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval)
12333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		goto done;
12343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT)
12353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent_uninit = 1;
12363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT_LEAF, &next_extent);
12373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval) {
12383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		has_next = 0;
12393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval != EXT2_ET_EXTENT_NO_NEXT)
12403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			goto done;
12413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	} else {
12423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		dbg_print_extent("set_bmap: next_extent",
12433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				 &next_extent);
12443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		has_next = 1;
12453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (next_extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT)
12463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			next_uninit = 1;
12473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
12483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_extent_goto(handle, logical);
12493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval && retval != EXT2_ET_EXTENT_NOT_FOUND)
12503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		goto done;
12513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_extent_get(handle, EXT2_EXTENT_PREV_LEAF, &prev_extent);
12523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval) {
12533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		has_prev = 0;
12543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval != EXT2_ET_EXTENT_NO_PREV)
12553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			goto done;
12563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	} else {
12573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		has_prev = 1;
12583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		dbg_print_extent("set_bmap: prev_extent",
12593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				 &prev_extent);
12603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (prev_extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT)
12613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			prev_uninit = 1;
12623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
12633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_extent_goto(handle, logical);
12643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval && retval != EXT2_ET_EXTENT_NOT_FOUND)
12653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		goto done;
12663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
12673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* check if already pointing to the requested physical */
12683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (mapped && (new_uninit == extent_uninit) &&
12693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	    (extent.e_pblk + (logical - extent.e_lblk) == physical)) {
12703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG
12713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		printf("physical block (at %llu) unchanged\n", logical);
12723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
12733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		goto done;
12743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
12753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
12763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!mapped) {
12773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG
12783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		printf("mapping unmapped logical block %llu\n", logical);
12793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
12803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if ((logical == extent.e_lblk + extent.e_len) &&
12813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    (physical == extent.e_pblk + extent.e_len) &&
12823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    (new_uninit == extent_uninit) &&
12833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    ((int) extent.e_len < max_len-1)) {
12843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			extent.e_len++;
12853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			retval = ext2fs_extent_replace(handle, 0, &extent);
12863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		} else if ((logical == extent.e_lblk - 1) &&
12873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			   (physical == extent.e_pblk - 1) &&
12883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			   (new_uninit == extent_uninit) &&
12893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			   ((int) extent.e_len < max_len - 1)) {
12903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			extent.e_len++;
12913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			extent.e_lblk--;
12923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			extent.e_pblk--;
12933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			retval = ext2fs_extent_replace(handle, 0, &extent);
12943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		} else if (has_next &&
12953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			   (logical == next_extent.e_lblk - 1) &&
12963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			   (physical == next_extent.e_pblk - 1) &&
12973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			   (new_uninit == next_uninit) &&
12983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			   ((int) next_extent.e_len < max_len - 1)) {
12993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			retval = ext2fs_extent_get(handle,
13003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt						   EXT2_EXTENT_NEXT_LEAF,
13013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt						   &next_extent);
13023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (retval)
13033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				goto done;
13043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			next_extent.e_len++;
13053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			next_extent.e_lblk--;
13063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			next_extent.e_pblk--;
13073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			retval = ext2fs_extent_replace(handle, 0, &next_extent);
13083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		} else if (logical < extent.e_lblk)
13093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			retval = ext2fs_extent_insert(handle, 0, &newextent);
13103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		else
13113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			retval = ext2fs_extent_insert(handle,
13123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				      EXT2_EXTENT_INSERT_AFTER, &newextent);
13133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
13143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			goto done;
13153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_extent_fix_parents(handle);
13163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
13173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			goto done;
13183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	} else if ((logical == extent.e_lblk) && (extent.e_len == 1))  {
13193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG
13203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		printf("(re/un)mapping only block in extent\n");
13213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
13223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (physical) {
13233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			retval = ext2fs_extent_replace(handle, 0, &newextent);
13243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		} else {
13253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			retval = ext2fs_extent_delete(handle, 0);
13263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (retval)
13273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				goto done;
13283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ec = ext2fs_extent_fix_parents(handle);
13293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (ec != EXT2_ET_NO_CURRENT_NODE)
13303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				retval = ec;
13313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
13323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
13333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
13343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			goto done;
13353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	} else if (logical == extent.e_lblk + extent.e_len - 1)  {
13363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG
13373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		printf("(re/un)mapping last block in extent\n");
13383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
13393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (physical) {
13403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (has_next &&
13413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			    (logical == (next_extent.e_lblk - 1)) &&
13423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			    (physical == (next_extent.e_pblk - 1)) &&
13433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			    (new_uninit == next_uninit) &&
13443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			    ((int) next_extent.e_len < max_len - 1)) {
13453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				retval = ext2fs_extent_get(handle,
13463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					EXT2_EXTENT_NEXT_LEAF, &next_extent);
13473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				if (retval)
13483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					goto done;
13493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				next_extent.e_len++;
13503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				next_extent.e_lblk--;
13513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				next_extent.e_pblk--;
13523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				retval = ext2fs_extent_replace(handle, 0,
13533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt							       &next_extent);
13543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				if (retval)
13553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					goto done;
13563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			} else
13573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				retval = ext2fs_extent_insert(handle,
13583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				      EXT2_EXTENT_INSERT_AFTER, &newextent);
13593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (retval)
13603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				goto done;
13613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			/* Now pointing at inserted extent; move back to prev */
13623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			retval = ext2fs_extent_get(handle,
13633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt						   EXT2_EXTENT_PREV_LEAF,
13643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt						   &extent);
13653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (retval)
13663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				goto done;
13673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
13683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent.e_len--;
13693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_extent_replace(handle, 0, &extent);
13703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
13713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			goto done;
13723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	} else if (logical == extent.e_lblk) {
13733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG
13743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		printf("(re/un)mapping first block in extent\n");
13753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
13763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (physical) {
13773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (has_prev &&
13783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			    (logical == (prev_extent.e_lblk +
13793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					 prev_extent.e_len)) &&
13803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			    (physical == (prev_extent.e_pblk +
13813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					  prev_extent.e_len)) &&
13823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			    (new_uninit == prev_uninit) &&
13833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			    ((int) prev_extent.e_len < max_len-1)) {
13843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				retval = ext2fs_extent_get(handle,
13853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					EXT2_EXTENT_PREV_LEAF, &prev_extent);
13863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				if (retval)
13873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					goto done;
13883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				prev_extent.e_len++;
13893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				retval = ext2fs_extent_replace(handle, 0,
13903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt							       &prev_extent);
13913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			} else
13923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				retval = ext2fs_extent_insert(handle,
13933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt							      0, &newextent);
13943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (retval)
13953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				goto done;
13963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			retval = ext2fs_extent_get(handle,
13973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt						   EXT2_EXTENT_NEXT_LEAF,
13983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt						   &extent);
13993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (retval)
14003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				goto done;
14013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
14023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent.e_pblk++;
14033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent.e_lblk++;
14043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent.e_len--;
14053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_extent_replace(handle, 0, &extent);
14063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
14073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			goto done;
14083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	} else {
14093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		__u32	orig_length;
14103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
14113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG
14123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		printf("(re/un)mapping in middle of extent\n");
14133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
14143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		/* need to split this extent; later */
14153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
14163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		orig_length = extent.e_len;
14173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
14183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		/* shorten pre-split extent */
14193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent.e_len = (logical - extent.e_lblk);
14203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_extent_replace(handle, 0, &extent);
14213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
14223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			goto done;
14233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		/* insert our new extent, if any */
14243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (physical) {
14253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			/* insert new extent after current */
14263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			retval = ext2fs_extent_insert(handle,
14273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					EXT2_EXTENT_INSERT_AFTER, &newextent);
14283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (retval)
14293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				goto done;
14303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
14313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		/* add post-split extent */
14323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent.e_pblk += extent.e_len + 1;
14333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent.e_lblk += extent.e_len + 1;
14343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent.e_len = orig_length - extent.e_len - 1;
14353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_extent_insert(handle,
14363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				EXT2_EXTENT_INSERT_AFTER, &extent);
14373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
14383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			goto done;
14393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
14403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
14413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtdone:
14423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* get handle back to its position */
14433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (orig_height > handle->max_depth)
14443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		orig_height = handle->max_depth; /* In case we shortened the tree */
14453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	extent_goto(handle, orig_height, orig_lblk);
14463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return retval;
14473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
14483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
14493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidterrcode_t ext2fs_extent_delete(ext2_extent_handle_t handle, int flags)
14503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
14513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct extent_path		*path;
14523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	char 				*cp;
14533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext3_extent_header	*eh;
14543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	errcode_t			retval = 0;
14553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
14563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE);
14573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
14583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!(handle->fs->flags & EXT2_FLAG_RW))
14593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EXT2_ET_RO_FILSYS;
14603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
14613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!handle->path)
14623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EXT2_ET_NO_CURRENT_NODE;
14633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
14643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG
14653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	{
14663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		struct ext2fs_extent	extent;
14673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
14683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT,
14693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					   &extent);
14703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval == 0) {
14713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			printf("extent delete %u ", handle->ino);
14723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			dbg_print_extent(0, &extent);
14733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
14743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
14753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
14763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
14773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	path = handle->path + handle->level;
14783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!path->curr)
14793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return EXT2_ET_NO_CURRENT_NODE;
14803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
14813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	cp = path->curr;
14823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
14833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (path->left) {
14843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		memmove(cp, cp + sizeof(struct ext3_extent_idx),
14853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			path->left * sizeof(struct ext3_extent_idx));
14863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		path->left--;
14873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	} else {
14883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		struct ext3_extent_idx	*ix = path->curr;
14893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ix--;
14903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		path->curr = ix;
14913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
14923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (--path->entries == 0)
14933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		path->curr = 0;
14943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
14953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* if non-root node has no entries left, remove it & parent ptr to it */
14963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (path->entries == 0 && handle->level) {
14973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (!(flags & EXT2_EXTENT_DELETE_KEEP_EMPTY)) {
14983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			struct ext2fs_extent	extent;
14993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
15003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			retval = ext2fs_extent_get(handle, EXT2_EXTENT_UP,
15013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt								&extent);
15023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (retval)
15033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				return retval;
15043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
15053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			retval = ext2fs_extent_delete(handle, flags);
15063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			handle->inode->i_blocks -= handle->fs->blocksize / 512;
15073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			retval = ext2fs_write_inode(handle->fs, handle->ino,
15083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt						    handle->inode);
15093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_block_alloc_stats(handle->fs, extent.e_pblk, -1);
15103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
15113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	} else {
15123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		eh = (struct ext3_extent_header *) path->buf;
15133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		eh->eh_entries = ext2fs_cpu_to_le16(path->entries);
15143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if ((path->entries == 0) && (handle->level == 0))
15153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			eh->eh_depth = handle->max_depth = 0;
15163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = update_path(handle);
15173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
15183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return retval;
15193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
15203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
15213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidterrcode_t ext2fs_extent_get_info(ext2_extent_handle_t handle,
15223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				 struct ext2_extent_info *info)
15233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
15243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct extent_path		*path;
15253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
15263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE);
15273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
15283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	memset(info, 0, sizeof(struct ext2_extent_info));
15293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
15303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	path = handle->path + handle->level;
15313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (path) {
15323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (path->curr)
15333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			info->curr_entry = ((char *) path->curr - path->buf) /
15343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				sizeof(struct ext3_extent_idx);
15353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		else
15363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			info->curr_entry = 0;
15373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		info->num_entries = path->entries;
15383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		info->max_entries = path->max_entries;
15393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		info->bytes_avail = (path->max_entries - path->entries) *
15403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			sizeof(struct ext3_extent);
15413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
15423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
15433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	info->curr_level = handle->level;
15443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	info->max_depth = handle->max_depth;
15453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	info->max_lblk = ((__u64) 1 << 32) - 1;
15463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	info->max_pblk = ((__u64) 1 << 48) - 1;
15473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	info->max_len = (1UL << 15);
15483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	info->max_uninit_len = (1UL << 15) - 1;
15493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
15503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return 0;
15513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
15523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
15533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG
15543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
15553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include "ss/ss.h"
15563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
15573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include "debugfs.h"
15583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
15593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt/*
15603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Hook in new commands into debugfs
15613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */
15623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtconst char *debug_prog_name = "tst_extents";
15633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtextern ss_request_table extent_cmds;
15643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtss_request_table *extra_cmds = &extent_cmds;
15653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
15663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtext2_ino_t	current_ino = 0;
15673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtext2_extent_handle_t current_handle;
15683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
15693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtint common_extent_args_process(int argc, char *argv[], int min_argc,
15703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			       int max_argc, const char *cmd,
15713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			       const char *usage, int flags)
15723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
15733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (common_args_process(argc, argv, min_argc, max_argc, cmd,
15743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				usage, flags))
15753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return 1;
15763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
15773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!current_handle) {
15783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		com_err(cmd, 0, "Extent handle not open");
15793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return 1;
15803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
15813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return 0;
15823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
15833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
15843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid do_inode(int argc, char *argv[])
15853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
15863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	ext2_ino_t	inode;
15873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int		i;
15883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext3_extent_header *eh;
15893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	errcode_t retval;
15903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
15913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (check_fs_open(argv[0]))
15923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
15933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
15943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (argc == 1) {
15953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (current_ino)
15963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			printf("Current inode is %d\n", current_ino);
15973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		else
15983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			printf("No current inode\n");
15993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
16003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
16013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
16023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (common_inode_args_process(argc, argv, &inode, 0)) {
16033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
16043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
16053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
16063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	current_ino = 0;
16073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
16083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_extent_open(current_fs, inode, &current_handle);
16093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval) {
16103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		com_err(argv[1], retval, "while opening extent handle");
16113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
16123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
16133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
16143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	current_ino = inode;
16153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
16163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	printf("Loaded inode %d\n", current_ino);
16173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
16183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return;
16193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
16203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
16213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid generic_goto_node(char *cmd_name, int op)
16223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
16233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext2fs_extent	extent;
16243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	errcode_t		retval;
16253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
16263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (check_fs_open(cmd_name))
16273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
16283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
16293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!current_handle) {
16303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		com_err(cmd_name, 0, "Extent handle not open");
16313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
16323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
16333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
16343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_extent_get(current_handle, op, &extent);
16353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval) {
16363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		com_err(cmd_name, retval, 0);
16373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
16383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
16393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	dbg_print_extent(0, &extent);
16403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
16413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
16423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid do_current_node(int argc, char *argv[])
16433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
16443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	generic_goto_node(argv[0], EXT2_EXTENT_CURRENT);
16453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
16463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
16473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid do_root_node(int argc, char *argv[])
16483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
16493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	generic_goto_node(argv[0], EXT2_EXTENT_ROOT);
16503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
16513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
16523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid do_last_leaf(int argc, char *argv[])
16533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
16543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	generic_goto_node(argv[0], EXT2_EXTENT_LAST_LEAF);
16553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
16563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
16573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid do_first_sib(int argc, char *argv[])
16583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
16593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	generic_goto_node(argv[0], EXT2_EXTENT_FIRST_SIB);
16603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
16613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
16623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid do_last_sib(int argc, char *argv[])
16633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
16643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	generic_goto_node(argv[0], EXT2_EXTENT_LAST_SIB);
16653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
16663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
16673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid do_next_sib(int argc, char *argv[])
16683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
16693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	generic_goto_node(argv[0], EXT2_EXTENT_NEXT_SIB);
16703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
16713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
16723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid do_prev_sib(int argc, char *argv[])
16733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
16743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	generic_goto_node(argv[0], EXT2_EXTENT_PREV_SIB);
16753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
16763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
16773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid do_next_leaf(int argc, char *argv[])
16783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
16793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	generic_goto_node(argv[0], EXT2_EXTENT_NEXT_LEAF);
16803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
16813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
16823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid do_prev_leaf(int argc, char *argv[])
16833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
16843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	generic_goto_node(argv[0], EXT2_EXTENT_PREV_LEAF);
16853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
16863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
16873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid do_next(int argc, char *argv[])
16883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
16893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	generic_goto_node(argv[0], EXT2_EXTENT_NEXT);
16903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
16913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
16923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid do_prev(int argc, char *argv[])
16933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
16943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	generic_goto_node(argv[0], EXT2_EXTENT_PREV);
16953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
16963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
16973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid do_up(int argc, char *argv[])
16983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
16993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	generic_goto_node(argv[0], EXT2_EXTENT_UP);
17003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
17013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
17023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid do_down(int argc, char *argv[])
17033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
17043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	generic_goto_node(argv[0], EXT2_EXTENT_DOWN);
17053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
17063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
17073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid do_delete_node(int argc, char *argv[])
17083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
17093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	errcode_t	retval;
17103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int		err;
17113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
17123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (common_extent_args_process(argc, argv, 1, 1, "delete_node",
17133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				       "", CHECK_FS_RW | CHECK_FS_BITMAPS))
17143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
17153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
17163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_extent_delete(current_handle, 0);
17173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval) {
17183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		com_err(argv[0], retval, 0);
17193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
17203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
17213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (current_handle->path && current_handle->path[0].curr)
17223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		do_current_node(argc, argv);
17233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
17243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
17253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid do_replace_node(int argc, char *argv[])
17263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
17273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	const char	*usage = "[--uninit] <lblk> <len> <pblk>";
17283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	errcode_t	retval;
17293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext2fs_extent extent;
17303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int err;
17313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
17323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (common_extent_args_process(argc, argv, 3, 5, "replace_node",
17333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				       usage, CHECK_FS_RW | CHECK_FS_BITMAPS))
17343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
17353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
17363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	extent.e_flags = 0;
17373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
17383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!strcmp(argv[1], "--uninit")) {
17393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		argc--;
17403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		argv++;
17413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		extent.e_flags |= EXT2_EXTENT_FLAGS_UNINIT;
17423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
17433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
17443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (argc != 4) {
17453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		fprintf(stderr, "Usage: %s %s\n", argv[0], usage);
17463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
17473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
17483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
17493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	extent.e_lblk = parse_ulong(argv[1], argv[0], "logical block", &err);
17503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (err)
17513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
17523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
17533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	extent.e_len = parse_ulong(argv[2], argv[0], "logical block", &err);
17543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (err)
17553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
17563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
17573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	extent.e_pblk = parse_ulong(argv[3], argv[0], "logical block", &err);
17583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (err)
17593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
17603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
17613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_extent_replace(current_handle, 0, &extent);
17623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval) {
17633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		com_err(argv[0], retval, 0);
17643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
17653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
17663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	do_current_node(argc, argv);
17673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
17683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
17693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid do_split_node(int argc, char *argv[])
17703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
17713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	errcode_t	retval;
17723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext2fs_extent extent;
17733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int err;
17743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
17753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (common_extent_args_process(argc, argv, 1, 1, "split_node",
17763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				       "", CHECK_FS_RW | CHECK_FS_BITMAPS))
17773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
17783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
17793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = extent_node_split(current_handle);
17803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval) {
17813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		com_err(argv[0], retval, 0);
17823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
17833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
17843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	do_current_node(argc, argv);
17853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
17863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
17873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid do_insert_node(int argc, char *argv[])
17883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
17893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	const char	*usage = "[--after] [--uninit] <lblk> <len> <pblk>";
17903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	errcode_t	retval;
17913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext2fs_extent extent;
17923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	char *cmd;
17933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int err;
17943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int flags = 0;
17953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
17963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (common_extent_args_process(argc, argv, 3, 6, "insert_node",
17973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				       usage, CHECK_FS_RW | CHECK_FS_BITMAPS))
17983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
17993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
18003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	cmd = argv[0];
18013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
18023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	extent.e_flags = 0;
18033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
18043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	while (argc > 2) {
18053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (!strcmp(argv[1], "--after")) {
18063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			argc--;
18073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			argv++;
18083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			flags |= EXT2_EXTENT_INSERT_AFTER;
18093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			continue;
18103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
18113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (!strcmp(argv[1], "--uninit")) {
18123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			argc--;
18133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			argv++;
18143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			extent.e_flags |= EXT2_EXTENT_FLAGS_UNINIT;
18153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			continue;
18163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
18173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		break;
18183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
18193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
18203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (argc != 4) {
18213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		fprintf(stderr, "usage: %s %s\n", cmd, usage);
18223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
18233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
18243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
18253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	extent.e_lblk = parse_ulong(argv[1], cmd,
18263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				    "logical block", &err);
18273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (err)
18283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
18293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
18303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	extent.e_len = parse_ulong(argv[2], cmd,
18313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				    "length", &err);
18323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (err)
18333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
18343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
18353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	extent.e_pblk = parse_ulong(argv[3], cmd,
18363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				    "pysical block", &err);
18373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (err)
18383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
18393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
18403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_extent_insert(current_handle, flags, &extent);
18413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval) {
18423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		com_err(cmd, retval, 0);
18433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
18443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
18453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	do_current_node(argc, argv);
18463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
18473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
18483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid do_set_bmap(int argc, char **argv)
18493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
18503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	const char	*usage = "[--uninit] <lblk> <pblk>";
18513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	errcode_t	retval;
18523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	blk_t		logical;
18533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	blk_t		physical;
18543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	char		*cmd = argv[0];
18553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int		flags = 0;
18563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int		err;
18573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
18583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (common_extent_args_process(argc, argv, 3, 5, "set_bmap",
18593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				       usage, CHECK_FS_RW | CHECK_FS_BITMAPS))
18603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
18613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
18623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (argc > 2 && !strcmp(argv[1], "--uninit")) {
18633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		argc--;
18643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		argv++;
18653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		flags |= EXT2_EXTENT_SET_BMAP_UNINIT;
18663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
18673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
18683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (argc != 3) {
18693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		fprintf(stderr, "Usage: %s %s\n", cmd, usage);
18703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
18713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
18723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
18733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	logical = parse_ulong(argv[1], cmd,
18743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				    "logical block", &err);
18753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (err)
18763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
18773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
18783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	physical = parse_ulong(argv[2], cmd,
18793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				    "physical block", &err);
18803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (err)
18813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
18823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
18833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_extent_set_bmap(current_handle, logical,
18843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					(blk64_t) physical, flags);
18853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval) {
18863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		com_err(cmd, retval, 0);
18873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
18883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
18893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (current_handle->path && current_handle->path[0].curr)
18903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		do_current_node(argc, argv);
18913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
18923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
18933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid do_print_all(int argc, char **argv)
18943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
18953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	const char	*usage = "[--leaf-only|--reverse|--reverse-leaf]";
18963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext2fs_extent	extent;
18973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	errcode_t		retval;
18983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	errcode_t		end_err = EXT2_ET_EXTENT_NO_NEXT;
18993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int			op = EXT2_EXTENT_NEXT;
19003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int			first_op = EXT2_EXTENT_ROOT;
19013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
19023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
19033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (common_extent_args_process(argc, argv, 1, 2, "print_all",
19043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				       usage, 0))
19053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
19063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
19073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (argc == 2) {
19083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (!strcmp(argv[1], "--leaf-only"))
19093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			op = EXT2_EXTENT_NEXT_LEAF;
19103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		else if (!strcmp(argv[1], "--reverse")) {
19113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			op = EXT2_EXTENT_PREV;
19123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			first_op = EXT2_EXTENT_LAST_LEAF;
19133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			end_err = EXT2_ET_EXTENT_NO_PREV;
19143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		} else if (!strcmp(argv[1], "--reverse-leaf")) {
19153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			op = EXT2_EXTENT_PREV_LEAF;
19163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			first_op = EXT2_EXTENT_LAST_LEAF;
19173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			end_err = EXT2_ET_EXTENT_NO_PREV;
19183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		} else {
19193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			fprintf(stderr, "Usage: %s %s\n", argv[0], usage);
19203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			return;
19213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
19223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
19233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
19243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_extent_get(current_handle, first_op, &extent);
19253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval) {
19263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		com_err(argv[0], retval, 0);
19273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
19283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
19293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	dbg_print_extent(0, &extent);
19303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
19313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	while (1) {
19323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = ext2fs_extent_get(current_handle, op, &extent);
19333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval == end_err)
19343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			break;
19353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
19363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval) {
19373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			com_err(argv[0], retval, 0);
19383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			return;
19393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
19403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		dbg_print_extent(0, &extent);
19413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
19423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
19433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
19443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid do_info(int argc, char **argv)
19453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
19463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext2fs_extent	extent;
19473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext2_extent_info	info;
19483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	errcode_t		retval;
19493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
19503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (common_extent_args_process(argc, argv, 1, 1, "info", "", 0))
19513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
19523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
19533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_extent_get_info(current_handle, &info);
19543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval) {
19553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		com_err(argv[0], retval, 0);
19563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
19573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
19583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
19593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_extent_get(current_handle,
19603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				   EXT2_EXTENT_CURRENT, &extent);
19613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval) {
19623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		com_err(argv[0], retval, 0);
19633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
19643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
19653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
19663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	dbg_print_extent(0, &extent);
19673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
19683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	printf("Current handle location: %d/%d (max: %d, bytes %d), level %d/%d\n",
19693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	       info.curr_entry, info.num_entries, info.max_entries,
19703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	       info.bytes_avail, info.curr_level, info.max_depth);
19713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	printf("\tmax lblk: %llu, max pblk: %llu\n", info.max_lblk,
19723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	       info.max_pblk);
19733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	printf("\tmax_len: %u, max_uninit_len: %u\n", info.max_len,
19743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	       info.max_uninit_len);
19753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
19763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
19773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid do_goto_block(int argc, char **argv)
19783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
19793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext2fs_extent	extent;
19803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	errcode_t		retval;
19813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int			op = EXT2_EXTENT_NEXT_LEAF;
19823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	blk_t			blk;
19833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int			level = 0;
19843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
19853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (common_extent_args_process(argc, argv, 2, 3, "goto_block",
19863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				       "block [level]", 0))
19873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
19883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
19893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (strtoblk(argv[0], argv[1], &blk))
19903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
19913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
19923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (argc == 3)
19933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (strtoblk(argv[0], argv[2], &level))
19943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			return;
19953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
19963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = extent_goto(current_handle, level, (blk64_t) blk);
19973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
19983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (retval) {
19993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		com_err(argv[0], retval,
20003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			"while trying to go to block %u, level %d",
20013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			blk, level);
20023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
20033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
20043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
20053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	generic_goto_node(argv[0], EXT2_EXTENT_CURRENT);
20063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
20073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
20083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2009