bmap.c revision 31dbecd482405e0d3a67eb58e1a1c8cb9f2ad83e
130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o/*
280e808fceb61c2061b32593c610893bf07a863eeTheodore Ts'o * bmap.c --- logical to physical block mapping
330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o *
430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o * Copyright (C) 1997 Theodore Ts'o.
530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o *
630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o * %Begin-Header%
730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o * This file may be redistributed under the terms of the GNU Public
830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o * License.
930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o * %End-Header%
1030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o */
1130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
1230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#include <stdio.h>
1330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#include <string.h>
1430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#if HAVE_UNISTD_H
1530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#include <unistd.h>
1630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#endif
1730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
18b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#if EXT2_FLAT_INCLUDES
19b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#include "ext2_fs.h"
20b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#else
2130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#include <linux/ext2_fs.h>
22b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#endif
2330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
2430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#include "ext2fs.h"
2530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
2678d8f90ffae45808096133c461ef1ee0e65de937Theodore Ts'o#if defined(__GNUC__) && !defined(NO_INLINE_FUNCS)
2730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#define _BMAP_INLINE_	__inline__
2830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#else
2930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#define _BMAP_INLINE_
3030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#endif
3130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
3231dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'oextern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino,
3330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			     struct ext2_inode *inode,
3430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			     char *block_buf, int bmap_flags,
3530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			     blk_t block, blk_t *phys_blk);
3630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
3730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#define BMAP_ALLOC	1
3830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
3930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#define inode_bmap(inode, nr) ((inode)->i_block[(nr)])
4030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
4130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'ostatic errcode_t _BMAP_INLINE_ block_ind_bmap(ext2_filsys fs, int flags,
4230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o					      blk_t ind, char *block_buf,
4330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o					      int *blocks_alloc,
4430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o					      blk_t nr, blk_t *ret_blk)
4530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o{
4630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	errcode_t	retval;
4730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	blk_t		b;
4830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
4930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if (!ind) {
5030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		*ret_blk = 0;
5130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		return 0;
5230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	}
5330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	retval = io_channel_read_blk(fs->io, ind, 1, block_buf);
5430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if (retval)
5530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		return retval;
5630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
5730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	b = ((blk_t *) block_buf)[nr];
5830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
5930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
6030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	    (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
6130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		b = ext2fs_swab32(b);
6230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
6330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if (!b && (flags & BMAP_ALLOC)) {
6430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		b = nr ? ((blk_t *) block_buf)[nr-1] : 0;
6530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		retval = ext2fs_alloc_block(fs, b,
6630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o					    block_buf + fs->blocksize, &b);
6730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		if (retval)
6830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			return retval;
6930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
7030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
7130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		    (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
7230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			((blk_t *) block_buf)[nr] = ext2fs_swab32(b);
7330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		else
7430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			((blk_t *) block_buf)[nr] = b;
7530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
7630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		retval = io_channel_write_blk(fs->io, ind, 1, block_buf);
7730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		if (retval)
7830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			return retval;
7930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
8030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		(*blocks_alloc)++;
8130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	}
8230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
8330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	*ret_blk = b;
8430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	return 0;
8530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o}
8630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
8730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'ostatic errcode_t _BMAP_INLINE_ block_dind_bmap(ext2_filsys fs, int flags,
8830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o					       blk_t dind, char *block_buf,
8930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o					       int *blocks_alloc,
9030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o					       blk_t nr, blk_t *ret_blk)
9130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o{
9230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	blk_t		b;
9330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	errcode_t	retval;
942eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o	blk_t		addr_per_block;
9530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
962eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o	addr_per_block = (blk_t) fs->blocksize >> 2;
9730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
9830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	retval = block_ind_bmap(fs, flags, dind, block_buf, blocks_alloc,
9930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o				nr / addr_per_block, &b);
10030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if (retval)
10130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		return retval;
10230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc,
10330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o				nr % addr_per_block, ret_blk);
10430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	return retval;
10530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o}
10630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
10730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'ostatic errcode_t _BMAP_INLINE_ block_tind_bmap(ext2_filsys fs, int flags,
10830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o					       blk_t tind, char *block_buf,
10930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o					       int *blocks_alloc,
11030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o					       blk_t nr, blk_t *ret_blk)
11130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o{
11230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	blk_t		b;
11330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	errcode_t	retval;
1142eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o	blk_t		addr_per_block;
11530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
1162eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o	addr_per_block = (blk_t) fs->blocksize >> 2;
11730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
11830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	retval = block_dind_bmap(fs, flags, tind, block_buf, blocks_alloc,
11930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o				 nr / addr_per_block, &b);
12030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if (retval)
12130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		return retval;
12230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc,
12330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o				nr % addr_per_block, ret_blk);
12430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	return retval;
12530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o}
12630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
12731dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'oerrcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode,
12830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		      char *block_buf, int bmap_flags, blk_t block,
12930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		      blk_t *phys_blk)
13030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o{
13130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	struct ext2_inode inode_buf;
1322eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o	blk_t addr_per_block;
13330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	blk_t	b;
13430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	char	*buf = 0;
13530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	errcode_t	retval = 0;
13630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	int		blocks_alloc = 0;
13730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
13830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	*phys_blk = 0;
13930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
14030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	/* Read inode structure if necessary */
14130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if (!inode) {
14230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		retval = ext2fs_read_inode(fs, ino, &inode_buf);
14330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		if (!retval)
14430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			return retval;
14530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		inode = &inode_buf;
14630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	}
1472eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o	addr_per_block = (blk_t) fs->blocksize >> 2;
14830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
14930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if (!block_buf) {
1507b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o		retval = ext2fs_get_mem(fs->blocksize * 2, (void **) &buf);
1517b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o		if (retval)
1527b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o			return retval;
15330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		block_buf = buf;
15430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	}
15530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
15630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if (block < EXT2_NDIR_BLOCKS) {
15730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		*phys_blk = inode_bmap(inode, block);
15830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		b = block ? inode_bmap(inode, block-1) : 0;
15930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
16030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) {
16130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			retval = ext2fs_alloc_block(fs, b, block_buf, &b);
16230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			if (retval)
16330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o				goto done;
16430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			inode_bmap(inode, block) = b;
16530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			blocks_alloc++;
16630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			*phys_blk = b;
16730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		}
16830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		goto done;
16930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	}
17030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
17130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	/* Indirect block */
17230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	block -= EXT2_NDIR_BLOCKS;
17330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if (block < addr_per_block) {
17430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		b = inode_bmap(inode, EXT2_IND_BLOCK);
17530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		if (!b) {
17630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			if (!(bmap_flags & BMAP_ALLOC))
17730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			    goto done;
17830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
17930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			b = inode_bmap(inode, EXT2_IND_BLOCK-1);
18030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 			retval = ext2fs_alloc_block(fs, b, block_buf, &b);
18130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			if (retval)
18230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o				goto done;
18330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			inode_bmap(inode, EXT2_IND_BLOCK) = b;
18430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			blocks_alloc++;
18530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		}
18630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		retval = block_ind_bmap(fs, bmap_flags, b, block_buf,
18730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o					&blocks_alloc, block, phys_blk);
18830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		goto done;
18930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	}
19030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
19130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	/* Doubly indirect block  */
19230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	block -= addr_per_block;
19330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if (block < addr_per_block * addr_per_block) {
19430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		b = inode_bmap(inode, EXT2_DIND_BLOCK);
19530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		if (!b) {
19630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			if (!(bmap_flags & BMAP_ALLOC))
19730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			    goto done;
19830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
19930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			b = inode_bmap(inode, EXT2_IND_BLOCK);
20030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 			retval = ext2fs_alloc_block(fs, b, block_buf, &b);
20130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			if (retval)
20230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o				goto done;
20330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			inode_bmap(inode, EXT2_DIND_BLOCK) = b;
20430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			blocks_alloc++;
20530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		}
20630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		retval = block_dind_bmap(fs, bmap_flags, b, block_buf,
20730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o					 &blocks_alloc, block, phys_blk);
20830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		goto done;
20930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	}
21030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
21130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	/* Triply indirect block */
21230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	block -= addr_per_block * addr_per_block;
21330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	b = inode_bmap(inode, EXT2_TIND_BLOCK);
21430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if (!b) {
21530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		if (!(bmap_flags & BMAP_ALLOC))
21630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			goto done;
21730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
21830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		b = inode_bmap(inode, EXT2_DIND_BLOCK);
21930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		retval = ext2fs_alloc_block(fs, b, block_buf, &b);
22030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		if (retval)
22130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			goto done;
22230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		inode_bmap(inode, EXT2_TIND_BLOCK) = b;
22330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		blocks_alloc++;
22430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	}
22530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	retval = block_tind_bmap(fs, bmap_flags, b, block_buf,
22630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o				 &blocks_alloc, block, phys_blk);
22730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'odone:
22830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if (buf)
2297b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o		ext2fs_free_mem((void **) &buf);
23030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if ((retval == 0) && blocks_alloc) {
23130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		inode->i_blocks += (blocks_alloc * fs->blocksize) / 512;
23230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		retval = ext2fs_write_inode(fs, ino, inode);
23330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	}
23430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	return retval;
23530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o}
23630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
23730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
23830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
239