bmap.c revision 5df55d7f847e29d23227592a0bb23daad1a61500
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#include "ext2_fs.h"
1930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#include "ext2fs.h"
2030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
2178d8f90ffae45808096133c461ef1ee0e65de937Theodore Ts'o#if defined(__GNUC__) && !defined(NO_INLINE_FUNCS)
2230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#define _BMAP_INLINE_	__inline__
2330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#else
2430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#define _BMAP_INLINE_
2530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#endif
2630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
2731dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'oextern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino,
2830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			     struct ext2_inode *inode,
2930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			     char *block_buf, int bmap_flags,
3030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			     blk_t block, blk_t *phys_blk);
3130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
3230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#define BMAP_ALLOC	1
3330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
3430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#define inode_bmap(inode, nr) ((inode)->i_block[(nr)])
3530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
3630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'ostatic errcode_t _BMAP_INLINE_ block_ind_bmap(ext2_filsys fs, int flags,
3730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o					      blk_t ind, char *block_buf,
3830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o					      int *blocks_alloc,
3930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o					      blk_t nr, blk_t *ret_blk)
4030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o{
4130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	errcode_t	retval;
4230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	blk_t		b;
4330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
4430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if (!ind) {
4530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		*ret_blk = 0;
4630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		return 0;
4730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	}
4830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	retval = io_channel_read_blk(fs->io, ind, 1, block_buf);
4930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if (retval)
5030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		return retval;
5130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
5230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	b = ((blk_t *) block_buf)[nr];
5330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
545df55d7f847e29d23227592a0bb23daad1a61500Theodore Ts'o#ifdef EXT2FS_ENABLE_SWAPFS
5530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
5630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	    (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
5730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		b = ext2fs_swab32(b);
585df55d7f847e29d23227592a0bb23daad1a61500Theodore Ts'o#endif
5930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
6030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if (!b && (flags & BMAP_ALLOC)) {
6130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		b = nr ? ((blk_t *) block_buf)[nr-1] : 0;
6230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		retval = ext2fs_alloc_block(fs, b,
6330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o					    block_buf + fs->blocksize, &b);
6430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		if (retval)
6530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			return retval;
6630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
675df55d7f847e29d23227592a0bb23daad1a61500Theodore Ts'o#ifdef EXT2FS_ENABLE_SWAPFS
6830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
6930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		    (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
7030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			((blk_t *) block_buf)[nr] = ext2fs_swab32(b);
7130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		else
725df55d7f847e29d23227592a0bb23daad1a61500Theodore Ts'o#endif
7330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			((blk_t *) block_buf)[nr] = b;
7430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
7530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		retval = io_channel_write_blk(fs->io, ind, 1, block_buf);
7630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		if (retval)
7730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			return retval;
7830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
7930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		(*blocks_alloc)++;
8030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	}
8130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
8230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	*ret_blk = b;
8330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	return 0;
8430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o}
8530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
8630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'ostatic errcode_t _BMAP_INLINE_ block_dind_bmap(ext2_filsys fs, int flags,
8730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o					       blk_t dind, char *block_buf,
8830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o					       int *blocks_alloc,
8930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o					       blk_t nr, blk_t *ret_blk)
9030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o{
9130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	blk_t		b;
9230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	errcode_t	retval;
932eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o	blk_t		addr_per_block;
9430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
952eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o	addr_per_block = (blk_t) fs->blocksize >> 2;
9630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
9730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	retval = block_ind_bmap(fs, flags, dind, block_buf, blocks_alloc,
9830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o				nr / addr_per_block, &b);
9930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if (retval)
10030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		return retval;
10130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc,
10230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o				nr % addr_per_block, ret_blk);
10330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	return retval;
10430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o}
10530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
10630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'ostatic errcode_t _BMAP_INLINE_ block_tind_bmap(ext2_filsys fs, int flags,
10730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o					       blk_t tind, char *block_buf,
10830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o					       int *blocks_alloc,
10930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o					       blk_t nr, blk_t *ret_blk)
11030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o{
11130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	blk_t		b;
11230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	errcode_t	retval;
1132eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o	blk_t		addr_per_block;
11430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
1152eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o	addr_per_block = (blk_t) fs->blocksize >> 2;
11630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
11730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	retval = block_dind_bmap(fs, flags, tind, block_buf, blocks_alloc,
11830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o				 nr / addr_per_block, &b);
11930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if (retval)
12030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		return retval;
12130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc,
12230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o				nr % addr_per_block, ret_blk);
12330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	return retval;
12430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o}
12530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
12631dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'oerrcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode,
12730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		      char *block_buf, int bmap_flags, blk_t block,
12830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		      blk_t *phys_blk)
12930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o{
13030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	struct ext2_inode inode_buf;
1312eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o	blk_t addr_per_block;
13230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	blk_t	b;
13330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	char	*buf = 0;
13430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	errcode_t	retval = 0;
13530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	int		blocks_alloc = 0;
13630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
13730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	*phys_blk = 0;
13830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
13930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	/* Read inode structure if necessary */
14030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if (!inode) {
14130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		retval = ext2fs_read_inode(fs, ino, &inode_buf);
14230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		if (!retval)
14330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			return retval;
14430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		inode = &inode_buf;
14530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	}
1462eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o	addr_per_block = (blk_t) fs->blocksize >> 2;
14730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
14830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if (!block_buf) {
1497b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o		retval = ext2fs_get_mem(fs->blocksize * 2, (void **) &buf);
1507b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o		if (retval)
1517b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o			return retval;
15230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		block_buf = buf;
15330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	}
15430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
15530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if (block < EXT2_NDIR_BLOCKS) {
15630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		*phys_blk = inode_bmap(inode, block);
15730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		b = block ? inode_bmap(inode, block-1) : 0;
15830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
15930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) {
16030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			retval = ext2fs_alloc_block(fs, b, block_buf, &b);
16130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			if (retval)
16230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o				goto done;
16330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			inode_bmap(inode, block) = b;
16430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			blocks_alloc++;
16530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			*phys_blk = b;
16630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		}
16730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		goto done;
16830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	}
16930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
17030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	/* Indirect block */
17130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	block -= EXT2_NDIR_BLOCKS;
17230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if (block < addr_per_block) {
17330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		b = inode_bmap(inode, EXT2_IND_BLOCK);
17430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		if (!b) {
17530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			if (!(bmap_flags & BMAP_ALLOC))
17630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			    goto done;
17730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
17830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			b = inode_bmap(inode, EXT2_IND_BLOCK-1);
17930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 			retval = ext2fs_alloc_block(fs, b, block_buf, &b);
18030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			if (retval)
18130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o				goto done;
18230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			inode_bmap(inode, EXT2_IND_BLOCK) = b;
18330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			blocks_alloc++;
18430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		}
18530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		retval = block_ind_bmap(fs, bmap_flags, b, block_buf,
18630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o					&blocks_alloc, block, phys_blk);
18730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		goto done;
18830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	}
18930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
19030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	/* Doubly indirect block  */
19130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	block -= addr_per_block;
19230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if (block < addr_per_block * addr_per_block) {
19330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		b = inode_bmap(inode, EXT2_DIND_BLOCK);
19430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		if (!b) {
19530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			if (!(bmap_flags & BMAP_ALLOC))
19630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			    goto done;
19730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
19830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			b = inode_bmap(inode, EXT2_IND_BLOCK);
19930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 			retval = ext2fs_alloc_block(fs, b, block_buf, &b);
20030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			if (retval)
20130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o				goto done;
20230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			inode_bmap(inode, EXT2_DIND_BLOCK) = b;
20330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			blocks_alloc++;
20430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		}
20530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		retval = block_dind_bmap(fs, bmap_flags, b, block_buf,
20630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o					 &blocks_alloc, block, phys_blk);
20730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		goto done;
20830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	}
20930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
21030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	/* Triply indirect block */
21130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	block -= addr_per_block * addr_per_block;
21230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	b = inode_bmap(inode, EXT2_TIND_BLOCK);
21330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if (!b) {
21430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		if (!(bmap_flags & BMAP_ALLOC))
21530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			goto done;
21630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
21730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		b = inode_bmap(inode, EXT2_DIND_BLOCK);
21830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		retval = ext2fs_alloc_block(fs, b, block_buf, &b);
21930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		if (retval)
22030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o			goto done;
22130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		inode_bmap(inode, EXT2_TIND_BLOCK) = b;
22230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		blocks_alloc++;
22330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	}
22430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	retval = block_tind_bmap(fs, bmap_flags, b, block_buf,
22530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o				 &blocks_alloc, block, phys_blk);
22630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'odone:
22730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if (buf)
2287b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o		ext2fs_free_mem((void **) &buf);
22930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	if ((retval == 0) && blocks_alloc) {
23030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		inode->i_blocks += (blocks_alloc * fs->blocksize) / 512;
23130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o		retval = ext2fs_write_inode(fs, ino, inode);
23230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	}
23330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o	return retval;
23430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o}
23530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
23630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
23730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o
238