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% 7543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * This file may be redistributed under the terms of the GNU Library 8543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * General Public License, version 2. 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 17cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o#include <errno.h> 1830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 19b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#include "ext2_fs.h" 20e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "ext2fsP.h" 2130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 2278d8f90ffae45808096133c461ef1ee0e65de937Theodore Ts'o#if defined(__GNUC__) && !defined(NO_INLINE_FUNCS) 2330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#define _BMAP_INLINE_ __inline__ 2430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#else 2530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#define _BMAP_INLINE_ 2630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#endif 2730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 2831dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'oextern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, 29efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o struct ext2_inode *inode, 3030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o char *block_buf, int bmap_flags, 3130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o blk_t block, blk_t *phys_blk); 3230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 3330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#define inode_bmap(inode, nr) ((inode)->i_block[(nr)]) 3430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 35efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ostatic _BMAP_INLINE_ errcode_t block_ind_bmap(ext2_filsys fs, int flags, 36efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o blk_t ind, char *block_buf, 3730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o int *blocks_alloc, 3830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o blk_t nr, blk_t *ret_blk) 3930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o{ 4030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o errcode_t retval; 4130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o blk_t b; 4230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 4330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (!ind) { 441d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o if (flags & BMAP_SET) 451d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o return EXT2_ET_SET_BMAP_NO_IND; 4630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o *ret_blk = 0; 4730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o return 0; 4830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 4930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o retval = io_channel_read_blk(fs->io, ind, 1, block_buf); 5030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (retval) 5130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o return retval; 5230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 531d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o if (flags & BMAP_SET) { 541d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o b = *ret_blk; 55126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o#ifdef WORDS_BIGENDIAN 56126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o b = ext2fs_swab32(b); 571d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o#endif 581d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o ((blk_t *) block_buf)[nr] = b; 591d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o return io_channel_write_blk(fs->io, ind, 1, block_buf); 601d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o } 611d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o 6230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o b = ((blk_t *) block_buf)[nr]; 6330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 64126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o#ifdef WORDS_BIGENDIAN 65126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o b = ext2fs_swab32(b); 665df55d7f847e29d23227592a0bb23daad1a61500Theodore Ts'o#endif 6730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 6830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (!b && (flags & BMAP_ALLOC)) { 6930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o b = nr ? ((blk_t *) block_buf)[nr-1] : 0; 7030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o retval = ext2fs_alloc_block(fs, b, 7130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o block_buf + fs->blocksize, &b); 7230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (retval) 7330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o return retval; 7430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 75126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o#ifdef WORDS_BIGENDIAN 76126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o ((blk_t *) block_buf)[nr] = ext2fs_swab32(b); 77126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o#else 78126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o ((blk_t *) block_buf)[nr] = b; 795df55d7f847e29d23227592a0bb23daad1a61500Theodore Ts'o#endif 8030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 8130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o retval = io_channel_write_blk(fs->io, ind, 1, block_buf); 8230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (retval) 8330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o return retval; 8430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 8530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o (*blocks_alloc)++; 8630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 8730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 8830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o *ret_blk = b; 8930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o return 0; 9030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o} 9130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 92546a1ff18cc912003883ff67ba3e87c69f700fc4Theodore Ts'ostatic _BMAP_INLINE_ errcode_t block_dind_bmap(ext2_filsys fs, int flags, 93efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o blk_t dind, char *block_buf, 9430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o int *blocks_alloc, 9530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o blk_t nr, blk_t *ret_blk) 9630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o{ 97e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk_t b = 0; 9830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o errcode_t retval; 992eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o blk_t addr_per_block; 100efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1012eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o addr_per_block = (blk_t) fs->blocksize >> 2; 10230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 103efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o retval = block_ind_bmap(fs, flags & ~BMAP_SET, dind, block_buf, 1041d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o blocks_alloc, nr / addr_per_block, &b); 10530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (retval) 10630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o return retval; 10730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc, 10830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o nr % addr_per_block, ret_blk); 10930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o return retval; 11030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o} 11130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 112546a1ff18cc912003883ff67ba3e87c69f700fc4Theodore Ts'ostatic _BMAP_INLINE_ errcode_t block_tind_bmap(ext2_filsys fs, int flags, 113efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o blk_t tind, char *block_buf, 11430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o int *blocks_alloc, 11530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o blk_t nr, blk_t *ret_blk) 11630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o{ 117e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk_t b = 0; 11830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o errcode_t retval; 1192eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o blk_t addr_per_block; 120efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1212eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o addr_per_block = (blk_t) fs->blocksize >> 2; 12230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 123efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o retval = block_dind_bmap(fs, flags & ~BMAP_SET, tind, block_buf, 1241d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o blocks_alloc, nr / addr_per_block, &b); 12530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (retval) 12630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o return retval; 12730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc, 12830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o nr % addr_per_block, ret_blk); 12930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o return retval; 13030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o} 13130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 132e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic errcode_t extent_bmap(ext2_filsys fs, ext2_ino_t ino, 133e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct ext2_inode *inode, 134e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_extent_handle_t handle, 135e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char *block_buf, int bmap_flags, blk64_t block, 136e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int *ret_flags, int *blocks_alloc, 137e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t *phys_blk); 138e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 139e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic errcode_t implied_cluster_alloc(ext2_filsys fs, ext2_ino_t ino, 140e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct ext2_inode *inode, 141e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_extent_handle_t handle, 142e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t lblk, blk64_t *phys_blk) 143e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 144e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t base_block, pblock = 0; 145e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int i; 146e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 147e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 148e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall EXT4_FEATURE_RO_COMPAT_BIGALLOC)) 149e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 150e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 151e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall base_block = lblk & ~EXT2FS_CLUSTER_MASK(fs); 152e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* 153e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Except for the logical block (lblk) that was passed in, search all 154e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * blocks in this logical cluster for a mapping to a physical cluster. 155e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * If any such map exists, calculate the physical block that maps to 156e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * the logical block and return that. 157e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 158e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * The old code wouldn't even look if (block % cluster_ratio) == 0; 159e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * this is incorrect if we're allocating blocks in reverse order. 160e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 161e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (i = 0; i < EXT2FS_CLUSTER_RATIO(fs); i++) { 162e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (base_block + i == lblk) 163e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 164e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall extent_bmap(fs, ino, inode, handle, 0, 0, 165e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall base_block + i, 0, 0, &pblock); 166e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (pblock) 167e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 168e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 169e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (pblock == 0) 170e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 171e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *phys_blk = pblock - i + (lblk - base_block); 172e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 173e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 174e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 175e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* Try to map a logical block to an already-allocated physical cluster. */ 176e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t ext2fs_map_cluster_block(ext2_filsys fs, ext2_ino_t ino, 177e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct ext2_inode *inode, blk64_t lblk, 178e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t *pblk) 179e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 180e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_extent_handle_t handle; 181e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode_t retval; 182e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 183e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Need bigalloc and extents to be enabled */ 184e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *pblk = 0; 185e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 186e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall EXT4_FEATURE_RO_COMPAT_BIGALLOC) || 187e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall !(inode->i_flags & EXT4_EXTENTS_FL)) 188e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 189e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 190e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_extent_open2(fs, ino, inode, &handle); 191e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval) 192e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 193e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 194e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = implied_cluster_alloc(fs, ino, inode, handle, lblk, pblk); 195e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval) 196e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out2; 197e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 198e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallout2: 199e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_extent_free(handle); 200e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallout: 201e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return retval; 202e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 203e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 204e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic errcode_t extent_bmap(ext2_filsys fs, ext2_ino_t ino, 205e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct ext2_inode *inode, 206e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_extent_handle_t handle, 207e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char *block_buf, int bmap_flags, blk64_t block, 208e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int *ret_flags, int *blocks_alloc, 209e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t *phys_blk) 210e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 211e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct ext2fs_extent extent; 212e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned int offset; 213e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode_t retval = 0; 214e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t blk64 = 0; 215e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int alloc = 0; 216e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 217e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (bmap_flags & BMAP_SET) { 218e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_extent_set_bmap(handle, block, 219e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *phys_blk, 0); 220e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return retval; 221e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 222e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_extent_goto(handle, block); 223e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval) { 224e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* If the extent is not found, return phys_blk = 0 */ 225e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval == EXT2_ET_EXTENT_NOT_FOUND) 226e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto got_block; 227e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return retval; 228e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 229e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent); 230e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval) 231e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return retval; 232e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall offset = block - extent.e_lblk; 233e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (block >= extent.e_lblk && (offset <= extent.e_len)) { 234e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *phys_blk = extent.e_pblk + offset; 235e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret_flags && extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT) 236e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *ret_flags |= BMAP_RET_UNINIT; 237e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 238e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallgot_block: 239e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) { 240e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall implied_cluster_alloc(fs, ino, inode, handle, block, &blk64); 241e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (blk64) 242e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto set_extent; 243e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = extent_bmap(fs, ino, inode, handle, block_buf, 244e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 0, block-1, 0, blocks_alloc, &blk64); 245e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval) 246e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64 = 0; 247e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_alloc_block2(fs, blk64, block_buf, 248e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall &blk64); 249e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval) 250e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return retval; 251e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64 &= ~EXT2FS_CLUSTER_MASK(fs); 252e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64 += EXT2FS_CLUSTER_MASK(fs) & block; 253e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall alloc++; 254e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall set_extent: 255e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_extent_set_bmap(handle, block, 256e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64, 0); 257e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval) 258e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return retval; 259e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Update inode after setting extent */ 260e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_read_inode(fs, ino, inode); 261e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval) 262e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return retval; 263e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *blocks_alloc += alloc; 264e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *phys_blk = blk64; 265e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 266e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 267e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 268e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 269e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallint ext2fs_file_block_offset_too_big(ext2_filsys fs, 270e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct ext2_inode *inode, 271e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t offset) 272e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 273e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t addr_per_block, max_map_block; 274e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 275e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Kernel seems to cut us off at 4294967294 blocks */ 276e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (offset >= (1ULL << 32) - 1) 277e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 1; 278e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 279e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (inode->i_flags & EXT4_EXTENTS_FL) 280e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 281e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 282e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall addr_per_block = fs->blocksize >> 2; 283e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall max_map_block = addr_per_block; 284e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall max_map_block += addr_per_block * addr_per_block; 285e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall max_map_block += addr_per_block * addr_per_block * addr_per_block; 286e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall max_map_block += 12; 287e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 288e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return offset >= max_map_block; 289e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 290e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 291cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'oerrcode_t ext2fs_bmap2(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode, 292cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o char *block_buf, int bmap_flags, blk64_t block, 293cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o int *ret_flags, blk64_t *phys_blk) 29430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o{ 29530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o struct ext2_inode inode_buf; 296cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o ext2_extent_handle_t handle = 0; 2972eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o blk_t addr_per_block; 298cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o blk_t b, blk32; 29930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o char *buf = 0; 30030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o errcode_t retval = 0; 3011d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o int blocks_alloc = 0, inode_dirty = 0; 30230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 3031d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o if (!(bmap_flags & BMAP_SET)) 3041d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o *phys_blk = 0; 30530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 306cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o if (ret_flags) 307cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o *ret_flags = 0; 308cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o 30930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o /* Read inode structure if necessary */ 31030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (!inode) { 31130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o retval = ext2fs_read_inode(fs, ino, &inode_buf); 312b38cd283637dafff6b39d4b76bf76fa2789eb21fTheodore Ts'o if (retval) 31330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o return retval; 31430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o inode = &inode_buf; 31530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 3162eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o addr_per_block = (blk_t) fs->blocksize >> 2; 31730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 318e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_file_block_offset_too_big(fs, inode, block)) 319e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return EXT2_ET_FILE_TOO_BIG; 3201e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wong 32130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (!block_buf) { 322ee01079a17bfecd17292ccd60058056fb3a8ba6cTheodore Ts'o retval = ext2fs_get_array(2, fs->blocksize, &buf); 3237b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 3247b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o return retval; 32530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o block_buf = buf; 32630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 32730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 328e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (inode->i_flags & EXT4_EXTENTS_FL) { 329e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_extent_open2(fs, ino, inode, &handle); 330e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval) 331e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto done; 332e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = extent_bmap(fs, ino, inode, handle, block_buf, 333e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall bmap_flags, block, ret_flags, 334e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall &blocks_alloc, phys_blk); 335e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto done; 336e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 337e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 33830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (block < EXT2_NDIR_BLOCKS) { 3391d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o if (bmap_flags & BMAP_SET) { 3401d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o b = *phys_blk; 3411d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o inode_bmap(inode, block) = b; 3421d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o inode_dirty++; 3431d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o goto done; 3441d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o } 3451d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o 34630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o *phys_blk = inode_bmap(inode, block); 34730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o b = block ? inode_bmap(inode, block-1) : 0; 348efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 34930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) { 35030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o retval = ext2fs_alloc_block(fs, b, block_buf, &b); 35130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (retval) 35230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o goto done; 35330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o inode_bmap(inode, block) = b; 35430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o blocks_alloc++; 35530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o *phys_blk = b; 35630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 35730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o goto done; 35830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 359efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 36030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o /* Indirect block */ 36130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o block -= EXT2_NDIR_BLOCKS; 362cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o blk32 = *phys_blk; 36330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (block < addr_per_block) { 36430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o b = inode_bmap(inode, EXT2_IND_BLOCK); 36530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (!b) { 3661d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o if (!(bmap_flags & BMAP_ALLOC)) { 3671d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o if (bmap_flags & BMAP_SET) 3681d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o retval = EXT2_ET_SET_BMAP_NO_IND; 3691d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o goto done; 3701d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o } 37130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 37230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o b = inode_bmap(inode, EXT2_IND_BLOCK-1); 37330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o retval = ext2fs_alloc_block(fs, b, block_buf, &b); 37430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (retval) 37530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o goto done; 37630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o inode_bmap(inode, EXT2_IND_BLOCK) = b; 37730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o blocks_alloc++; 37830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 379efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o retval = block_ind_bmap(fs, bmap_flags, b, block_buf, 380cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o &blocks_alloc, block, &blk32); 381cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o if (retval == 0) 382cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o *phys_blk = blk32; 38330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o goto done; 38430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 385efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 38630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o /* Doubly indirect block */ 38730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o block -= addr_per_block; 38830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (block < addr_per_block * addr_per_block) { 38930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o b = inode_bmap(inode, EXT2_DIND_BLOCK); 39030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (!b) { 3911d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o if (!(bmap_flags & BMAP_ALLOC)) { 3921d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o if (bmap_flags & BMAP_SET) 3931d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o retval = EXT2_ET_SET_BMAP_NO_IND; 3941d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o goto done; 3951d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o } 39630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 39730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o b = inode_bmap(inode, EXT2_IND_BLOCK); 39830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o retval = ext2fs_alloc_block(fs, b, block_buf, &b); 39930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (retval) 40030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o goto done; 40130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o inode_bmap(inode, EXT2_DIND_BLOCK) = b; 40230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o blocks_alloc++; 40330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 404efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o retval = block_dind_bmap(fs, bmap_flags, b, block_buf, 405cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o &blocks_alloc, block, &blk32); 406cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o if (retval == 0) 407cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o *phys_blk = blk32; 40830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o goto done; 40930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 41030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 41130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o /* Triply indirect block */ 41230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o block -= addr_per_block * addr_per_block; 41330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o b = inode_bmap(inode, EXT2_TIND_BLOCK); 41430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (!b) { 4151d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o if (!(bmap_flags & BMAP_ALLOC)) { 4161d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o if (bmap_flags & BMAP_SET) 4171d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o retval = EXT2_ET_SET_BMAP_NO_IND; 41830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o goto done; 4191d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o } 42030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 42130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o b = inode_bmap(inode, EXT2_DIND_BLOCK); 42230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o retval = ext2fs_alloc_block(fs, b, block_buf, &b); 42330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (retval) 42430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o goto done; 42530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o inode_bmap(inode, EXT2_TIND_BLOCK) = b; 42630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o blocks_alloc++; 42730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 428efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o retval = block_tind_bmap(fs, bmap_flags, b, block_buf, 429cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o &blocks_alloc, block, &blk32); 430cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o if (retval == 0) 431cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o *phys_blk = blk32; 43230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'odone: 43330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (buf) 434c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&buf); 435cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o if (handle) 436cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o ext2fs_extent_free(handle); 4371d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o if ((retval == 0) && (blocks_alloc || inode_dirty)) { 4381ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o ext2fs_iblk_add_blocks(fs, inode, blocks_alloc); 43930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o retval = ext2fs_write_inode(fs, ino, inode); 44030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 44130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o return retval; 44230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o} 44330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 444cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'oerrcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode, 445cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o char *block_buf, int bmap_flags, blk_t block, 446cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o blk_t *phys_blk) 447cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o{ 448cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o errcode_t ret; 4499c9e1d5fe507d08309e9815eee50ca73e21bd2bdTheodore Ts'o blk64_t ret_blk = *phys_blk; 450cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o 451cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o ret = ext2fs_bmap2(fs, ino, inode, block_buf, bmap_flags, block, 452cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o 0, &ret_blk); 453cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o if (ret) 454cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o return ret; 455cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o if (ret_blk >= ((long long) 1 << 32)) 456cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o return EOVERFLOW; 457cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o *phys_blk = ret_blk; 458cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o return 0; 459cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o} 460