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 12d1154eb460efe588eaed3d439c1caaca149fa362Theodore Ts'o#include "config.h" 1330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#include <stdio.h> 1430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#include <string.h> 1530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#if HAVE_UNISTD_H 1630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#include <unistd.h> 1730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#endif 18cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o#include <errno.h> 1930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 20b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#include "ext2_fs.h" 21f404167dda29a59d2be2882328aeb074b9899669Theodore Ts'o#include "ext2fsP.h" 2230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 2378d8f90ffae45808096133c461ef1ee0e65de937Theodore Ts'o#if defined(__GNUC__) && !defined(NO_INLINE_FUNCS) 2430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#define _BMAP_INLINE_ __inline__ 2530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#else 2630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#define _BMAP_INLINE_ 2730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#endif 2830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 2931dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'oextern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, 30efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o struct ext2_inode *inode, 3130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o char *block_buf, int bmap_flags, 3230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o blk_t block, blk_t *phys_blk); 3330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 3430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#define inode_bmap(inode, nr) ((inode)->i_block[(nr)]) 3530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 36efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ostatic _BMAP_INLINE_ errcode_t block_ind_bmap(ext2_filsys fs, int flags, 37efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore 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) { 451d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o if (flags & BMAP_SET) 461d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o return EXT2_ET_SET_BMAP_NO_IND; 4730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o *ret_blk = 0; 4830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o return 0; 4930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 5030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o retval = io_channel_read_blk(fs->io, ind, 1, block_buf); 5130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (retval) 5230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o return retval; 5330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 541d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o if (flags & BMAP_SET) { 551d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o b = *ret_blk; 56126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o#ifdef WORDS_BIGENDIAN 57126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o b = ext2fs_swab32(b); 581d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o#endif 591d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o ((blk_t *) block_buf)[nr] = b; 601d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o return io_channel_write_blk(fs->io, ind, 1, block_buf); 611d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o } 621d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o 6330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o b = ((blk_t *) block_buf)[nr]; 6430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 65126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o#ifdef WORDS_BIGENDIAN 66126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o b = ext2fs_swab32(b); 675df55d7f847e29d23227592a0bb23daad1a61500Theodore Ts'o#endif 6830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 6930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (!b && (flags & BMAP_ALLOC)) { 70407916f5af4443e0ddd9469c57fc1684c07f9294Darrick J. Wong b = nr ? ext2fs_le32_to_cpu(((blk_t *)block_buf)[nr - 1]) : ind; 7130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o retval = ext2fs_alloc_block(fs, b, 7230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o block_buf + fs->blocksize, &b); 7330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (retval) 7430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o return retval; 7530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 76126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o#ifdef WORDS_BIGENDIAN 77126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o ((blk_t *) block_buf)[nr] = ext2fs_swab32(b); 78126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o#else 79126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o ((blk_t *) block_buf)[nr] = b; 805df55d7f847e29d23227592a0bb23daad1a61500Theodore Ts'o#endif 8130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 8230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o retval = io_channel_write_blk(fs->io, ind, 1, block_buf); 8330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (retval) 8430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o return retval; 8530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 8630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o (*blocks_alloc)++; 8730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 8830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 8930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o *ret_blk = b; 9030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o return 0; 9130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o} 9230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 93546a1ff18cc912003883ff67ba3e87c69f700fc4Theodore Ts'ostatic _BMAP_INLINE_ errcode_t block_dind_bmap(ext2_filsys fs, int flags, 94efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o blk_t dind, char *block_buf, 9530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o int *blocks_alloc, 9630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o blk_t nr, blk_t *ret_blk) 9730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o{ 981d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger blk_t b = 0; 9930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o errcode_t retval; 1002eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o blk_t addr_per_block; 101efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1022eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o addr_per_block = (blk_t) fs->blocksize >> 2; 10330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 104efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o retval = block_ind_bmap(fs, flags & ~BMAP_SET, dind, block_buf, 1051d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o blocks_alloc, nr / addr_per_block, &b); 10630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (retval) 10730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o return retval; 10830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc, 10930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o nr % addr_per_block, ret_blk); 11030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o return retval; 11130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o} 11230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 113546a1ff18cc912003883ff67ba3e87c69f700fc4Theodore Ts'ostatic _BMAP_INLINE_ errcode_t block_tind_bmap(ext2_filsys fs, int flags, 114efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o blk_t tind, char *block_buf, 11530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o int *blocks_alloc, 11630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o blk_t nr, blk_t *ret_blk) 11730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o{ 1181d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger blk_t b = 0; 11930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o errcode_t retval; 1202eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o blk_t addr_per_block; 121efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1222eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o addr_per_block = (blk_t) fs->blocksize >> 2; 12330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 124efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o retval = block_dind_bmap(fs, flags & ~BMAP_SET, tind, block_buf, 1251d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o blocks_alloc, nr / addr_per_block, &b); 12630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (retval) 12730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o return retval; 12830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc, 12930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o nr % addr_per_block, ret_blk); 13030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o return retval; 13130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o} 13230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 133551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'ostatic errcode_t extent_bmap(ext2_filsys fs, ext2_ino_t ino, 134551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o struct ext2_inode *inode, 135551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o ext2_extent_handle_t handle, 136551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o char *block_buf, int bmap_flags, blk64_t block, 137551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o int *ret_flags, int *blocks_alloc, 1388e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o blk64_t *phys_blk); 1398e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o 1408e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'ostatic errcode_t implied_cluster_alloc(ext2_filsys fs, ext2_ino_t ino, 1418e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o struct ext2_inode *inode, 1428e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o ext2_extent_handle_t handle, 1432a091427bcbff1fd1cf3f0bccf00da98d52b8f16Darrick J. Wong blk64_t lblk, blk64_t *phys_blk) 1448e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o{ 1458e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o blk64_t base_block, pblock = 0; 1468e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o int i; 1478e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o 14877b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_bigalloc(fs->super)) 1498e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o return 0; 1508e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o 1512a091427bcbff1fd1cf3f0bccf00da98d52b8f16Darrick J. Wong base_block = lblk & ~EXT2FS_CLUSTER_MASK(fs); 1522a091427bcbff1fd1cf3f0bccf00da98d52b8f16Darrick J. Wong /* 1532a091427bcbff1fd1cf3f0bccf00da98d52b8f16Darrick J. Wong * Except for the logical block (lblk) that was passed in, search all 1542a091427bcbff1fd1cf3f0bccf00da98d52b8f16Darrick J. Wong * blocks in this logical cluster for a mapping to a physical cluster. 1552a091427bcbff1fd1cf3f0bccf00da98d52b8f16Darrick J. Wong * If any such map exists, calculate the physical block that maps to 1562a091427bcbff1fd1cf3f0bccf00da98d52b8f16Darrick J. Wong * the logical block and return that. 1572a091427bcbff1fd1cf3f0bccf00da98d52b8f16Darrick J. Wong * 1582a091427bcbff1fd1cf3f0bccf00da98d52b8f16Darrick J. Wong * The old code wouldn't even look if (block % cluster_ratio) == 0; 1592a091427bcbff1fd1cf3f0bccf00da98d52b8f16Darrick J. Wong * this is incorrect if we're allocating blocks in reverse order. 1602a091427bcbff1fd1cf3f0bccf00da98d52b8f16Darrick J. Wong */ 1618e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o for (i = 0; i < EXT2FS_CLUSTER_RATIO(fs); i++) { 1622a091427bcbff1fd1cf3f0bccf00da98d52b8f16Darrick J. Wong if (base_block + i == lblk) 1632a091427bcbff1fd1cf3f0bccf00da98d52b8f16Darrick J. Wong continue; 1648e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o extent_bmap(fs, ino, inode, handle, 0, 0, 1658e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o base_block + i, 0, 0, &pblock); 1668e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o if (pblock) 1678e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o break; 1688e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o } 1698e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o if (pblock == 0) 1708e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o return 0; 1712a091427bcbff1fd1cf3f0bccf00da98d52b8f16Darrick J. Wong *phys_blk = pblock - i + (lblk - base_block); 1728e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o return 0; 1738e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o} 1748e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o 17584397754250d13e8596dd68c157c4c9863800079Darrick J. Wong/* Try to map a logical block to an already-allocated physical cluster. */ 17684397754250d13e8596dd68c157c4c9863800079Darrick J. Wongerrcode_t ext2fs_map_cluster_block(ext2_filsys fs, ext2_ino_t ino, 17784397754250d13e8596dd68c157c4c9863800079Darrick J. Wong struct ext2_inode *inode, blk64_t lblk, 17884397754250d13e8596dd68c157c4c9863800079Darrick J. Wong blk64_t *pblk) 17984397754250d13e8596dd68c157c4c9863800079Darrick J. Wong{ 18084397754250d13e8596dd68c157c4c9863800079Darrick J. Wong ext2_extent_handle_t handle; 18184397754250d13e8596dd68c157c4c9863800079Darrick J. Wong errcode_t retval; 18284397754250d13e8596dd68c157c4c9863800079Darrick J. Wong 18384397754250d13e8596dd68c157c4c9863800079Darrick J. Wong /* Need bigalloc and extents to be enabled */ 18484397754250d13e8596dd68c157c4c9863800079Darrick J. Wong *pblk = 0; 18577b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_bigalloc(fs->super) || 18684397754250d13e8596dd68c157c4c9863800079Darrick J. Wong !(inode->i_flags & EXT4_EXTENTS_FL)) 18784397754250d13e8596dd68c157c4c9863800079Darrick J. Wong return 0; 18884397754250d13e8596dd68c157c4c9863800079Darrick J. Wong 18984397754250d13e8596dd68c157c4c9863800079Darrick J. Wong retval = ext2fs_extent_open2(fs, ino, inode, &handle); 19084397754250d13e8596dd68c157c4c9863800079Darrick J. Wong if (retval) 19184397754250d13e8596dd68c157c4c9863800079Darrick J. Wong goto out; 19284397754250d13e8596dd68c157c4c9863800079Darrick J. Wong 19384397754250d13e8596dd68c157c4c9863800079Darrick J. Wong retval = implied_cluster_alloc(fs, ino, inode, handle, lblk, pblk); 19484397754250d13e8596dd68c157c4c9863800079Darrick J. Wong if (retval) 19584397754250d13e8596dd68c157c4c9863800079Darrick J. Wong goto out2; 19684397754250d13e8596dd68c157c4c9863800079Darrick J. Wong 19784397754250d13e8596dd68c157c4c9863800079Darrick J. Wongout2: 19884397754250d13e8596dd68c157c4c9863800079Darrick J. Wong ext2fs_extent_free(handle); 19984397754250d13e8596dd68c157c4c9863800079Darrick J. Wongout: 20084397754250d13e8596dd68c157c4c9863800079Darrick J. Wong return retval; 20184397754250d13e8596dd68c157c4c9863800079Darrick J. Wong} 20284397754250d13e8596dd68c157c4c9863800079Darrick J. Wong 2038e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'ostatic errcode_t extent_bmap(ext2_filsys fs, ext2_ino_t ino, 2048e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o struct ext2_inode *inode, 2058e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o ext2_extent_handle_t handle, 2068e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o char *block_buf, int bmap_flags, blk64_t block, 2078e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o int *ret_flags, int *blocks_alloc, 208551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o blk64_t *phys_blk) 209551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o{ 210127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht struct blk_alloc_ctx alloc_ctx; 211551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o struct ext2fs_extent extent; 212551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o unsigned int offset; 213551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o errcode_t retval = 0; 2148e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o blk64_t blk64 = 0; 2158e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o int alloc = 0; 21660a212f773ba116b4f7a9edb5eb76b40668ea8a0Darrick J. Wong int set_flags; 21760a212f773ba116b4f7a9edb5eb76b40668ea8a0Darrick J. Wong 21860a212f773ba116b4f7a9edb5eb76b40668ea8a0Darrick J. Wong set_flags = bmap_flags & BMAP_UNINIT ? EXT2_EXTENT_SET_BMAP_UNINIT : 0; 219551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o 220551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o if (bmap_flags & BMAP_SET) { 221551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o retval = ext2fs_extent_set_bmap(handle, block, 22260a212f773ba116b4f7a9edb5eb76b40668ea8a0Darrick J. Wong *phys_blk, set_flags); 223551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o return retval; 224551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o } 225551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o retval = ext2fs_extent_goto(handle, block); 226551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o if (retval) { 227551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o /* If the extent is not found, return phys_blk = 0 */ 228551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o if (retval == EXT2_ET_EXTENT_NOT_FOUND) 229551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o goto got_block; 230551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o return retval; 231551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o } 232551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent); 233551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o if (retval) 234551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o return retval; 235551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o offset = block - extent.e_lblk; 236551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o if (block >= extent.e_lblk && (offset <= extent.e_len)) { 237551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o *phys_blk = extent.e_pblk + offset; 238551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o if (ret_flags && extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT) 239551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o *ret_flags |= BMAP_RET_UNINIT; 240551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o } 241551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'ogot_block: 242551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) { 2438e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o implied_cluster_alloc(fs, ino, inode, handle, block, &blk64); 2448e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o if (blk64) 2458e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o goto set_extent; 246551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o retval = extent_bmap(fs, ino, inode, handle, block_buf, 247551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o 0, block-1, 0, blocks_alloc, &blk64); 248551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o if (retval) 2497b486ec08cda3bc67b7f6bdcbcc9cb5783322e6cDarrick J. Wong blk64 = ext2fs_find_inode_goal(fs, ino, inode, block); 250127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht alloc_ctx.ino = ino; 251127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht alloc_ctx.inode = inode; 252127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht alloc_ctx.lblk = extent.e_lblk; 253127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht alloc_ctx.flags = BLOCK_ALLOC_DATA; 254127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht retval = ext2fs_alloc_block3(fs, blk64, block_buf, &blk64, 255127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht &alloc_ctx); 256551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o if (retval) 257551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o return retval; 2588e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o blk64 &= ~EXT2FS_CLUSTER_MASK(fs); 2598e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o blk64 += EXT2FS_CLUSTER_MASK(fs) & block; 2608e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o alloc++; 2618e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o set_extent: 262551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o retval = ext2fs_extent_set_bmap(handle, block, 26360a212f773ba116b4f7a9edb5eb76b40668ea8a0Darrick J. Wong blk64, set_flags); 2646225a154d2616edcd13885797ed5e1c0cc51e0b7Darrick J. Wong if (retval) { 2656225a154d2616edcd13885797ed5e1c0cc51e0b7Darrick J. Wong ext2fs_block_alloc_stats2(fs, blk64, -1); 266551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o return retval; 2676225a154d2616edcd13885797ed5e1c0cc51e0b7Darrick J. Wong } 268551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o /* Update inode after setting extent */ 269551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o retval = ext2fs_read_inode(fs, ino, inode); 270551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o if (retval) 271551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o return retval; 2728e8a190fa212ca28efb2e8a8b3318a24d7fc4b7aTheodore Ts'o *blocks_alloc += alloc; 273551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o *phys_blk = blk64; 274551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o } 275551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o return 0; 276551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o} 277551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o 2781e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wongint ext2fs_file_block_offset_too_big(ext2_filsys fs, 2791e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wong struct ext2_inode *inode, 2801e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wong blk64_t offset) 2811e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wong{ 2821e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wong blk64_t addr_per_block, max_map_block; 2831e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wong 2841e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wong /* Kernel seems to cut us off at 4294967294 blocks */ 2851e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wong if (offset >= (1ULL << 32) - 1) 2861e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wong return 1; 2871e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wong 2881e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wong if (inode->i_flags & EXT4_EXTENTS_FL) 2891e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wong return 0; 2901e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wong 2911e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wong addr_per_block = fs->blocksize >> 2; 2921e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wong max_map_block = addr_per_block; 2931e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wong max_map_block += addr_per_block * addr_per_block; 2941e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wong max_map_block += addr_per_block * addr_per_block * addr_per_block; 2951e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wong max_map_block += 12; 2961e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wong 2971e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wong return offset >= max_map_block; 2981e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wong} 299551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o 300cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'oerrcode_t ext2fs_bmap2(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode, 301cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o char *block_buf, int bmap_flags, blk64_t block, 302cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o int *ret_flags, blk64_t *phys_blk) 30330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o{ 30430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o struct ext2_inode inode_buf; 305cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o ext2_extent_handle_t handle = 0; 3062eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o blk_t addr_per_block; 307cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o blk_t b, blk32; 308127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht blk64_t b64; 30930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o char *buf = 0; 31030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o errcode_t retval = 0; 3111d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o int blocks_alloc = 0, inode_dirty = 0; 312127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht struct blk_alloc_ctx alloc_ctx = { 313127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht .ino = ino, 314127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht .inode = inode, 315127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht .lblk = 0, 316127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht .flags = BLOCK_ALLOC_DATA, 317127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht }; 31830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 3191d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o if (!(bmap_flags & BMAP_SET)) 3201d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o *phys_blk = 0; 32130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 322cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o if (ret_flags) 323cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o *ret_flags = 0; 324cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o 32530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o /* Read inode structure if necessary */ 32630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (!inode) { 32730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o retval = ext2fs_read_inode(fs, ino, &inode_buf); 328b38cd283637dafff6b39d4b76bf76fa2789eb21fTheodore Ts'o if (retval) 32930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o return retval; 33030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o inode = &inode_buf; 33130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 3322eb374c9401079aa56aa12f0047ca3866e69b754Theodore Ts'o addr_per_block = (blk_t) fs->blocksize >> 2; 33330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 3341e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wong if (ext2fs_file_block_offset_too_big(fs, inode, block)) 3351e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wong return EXT2_ET_FILE_TOO_BIG; 3361e7451493ed67ae94ba5c1d2bed059527bc9848dDarrick J. Wong 337f5f6c020cac429a5484ad0fdaccb44f127912075Zheng Liu /* 338f5f6c020cac429a5484ad0fdaccb44f127912075Zheng Liu * If an inode has inline data, that means that it doesn't have 339f5f6c020cac429a5484ad0fdaccb44f127912075Zheng Liu * any blocks and we shouldn't map any blocks for it. 340f5f6c020cac429a5484ad0fdaccb44f127912075Zheng Liu */ 341f5f6c020cac429a5484ad0fdaccb44f127912075Zheng Liu if (inode->i_flags & EXT4_INLINE_DATA_FL) 342f5f6c020cac429a5484ad0fdaccb44f127912075Zheng Liu return EXT2_ET_INLINE_DATA_NO_BLOCK; 343f5f6c020cac429a5484ad0fdaccb44f127912075Zheng Liu 34430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (!block_buf) { 345ee01079a17bfecd17292ccd60058056fb3a8ba6cTheodore Ts'o retval = ext2fs_get_array(2, fs->blocksize, &buf); 3467b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 3477b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o return retval; 34830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o block_buf = buf; 34930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 35030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 351551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o if (inode->i_flags & EXT4_EXTENTS_FL) { 352551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o retval = ext2fs_extent_open2(fs, ino, inode, &handle); 353551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o if (retval) 354551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o goto done; 355551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o retval = extent_bmap(fs, ino, inode, handle, block_buf, 356551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o bmap_flags, block, ret_flags, 357551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o &blocks_alloc, phys_blk); 358551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o goto done; 359551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o } 360551e2e46ee2fdf8cfa16e153d3c560203f0f9a5eTheodore Ts'o 36130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (block < EXT2_NDIR_BLOCKS) { 3621d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o if (bmap_flags & BMAP_SET) { 3631d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o b = *phys_blk; 3641d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o inode_bmap(inode, block) = b; 3651d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o inode_dirty++; 3661d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o goto done; 3671d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o } 3681d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o 36930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o *phys_blk = inode_bmap(inode, block); 3707b486ec08cda3bc67b7f6bdcbcc9cb5783322e6cDarrick J. Wong b = block ? inode_bmap(inode, block - 1) : 3717b486ec08cda3bc67b7f6bdcbcc9cb5783322e6cDarrick J. Wong ext2fs_find_inode_goal(fs, ino, inode, block); 372efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 37330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) { 374127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht b64 = b; 375127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht retval = ext2fs_alloc_block3(fs, b64, block_buf, &b64, 376127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht &alloc_ctx); 377127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht b = b64; 37830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (retval) 37930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o goto done; 38030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o inode_bmap(inode, block) = b; 38130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o blocks_alloc++; 38230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o *phys_blk = b; 38330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 38430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o goto done; 38530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 386efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 38730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o /* Indirect block */ 38830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o block -= EXT2_NDIR_BLOCKS; 389cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o blk32 = *phys_blk; 39030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (block < addr_per_block) { 39130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o b = inode_bmap(inode, EXT2_IND_BLOCK); 39230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (!b) { 3931d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o if (!(bmap_flags & BMAP_ALLOC)) { 3941d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o if (bmap_flags & BMAP_SET) 3951d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o retval = EXT2_ET_SET_BMAP_NO_IND; 3961d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o goto done; 3971d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o } 39830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 39930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o b = inode_bmap(inode, EXT2_IND_BLOCK-1); 400127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht b64 = b; 401127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht retval = ext2fs_alloc_block3(fs, b64, block_buf, &b64, 402127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht &alloc_ctx); 403127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht b = b64; 40430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (retval) 40530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o goto done; 40630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o inode_bmap(inode, EXT2_IND_BLOCK) = b; 40730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o blocks_alloc++; 40830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 409efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o retval = block_ind_bmap(fs, bmap_flags, b, block_buf, 410cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o &blocks_alloc, block, &blk32); 411cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o if (retval == 0) 412cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o *phys_blk = blk32; 41330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o goto done; 41430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 415efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 41630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o /* Doubly indirect block */ 41730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o block -= addr_per_block; 41830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (block < addr_per_block * addr_per_block) { 41930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o b = inode_bmap(inode, EXT2_DIND_BLOCK); 42030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (!b) { 4211d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o if (!(bmap_flags & BMAP_ALLOC)) { 4221d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o if (bmap_flags & BMAP_SET) 4231d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o retval = EXT2_ET_SET_BMAP_NO_IND; 4241d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o goto done; 4251d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o } 42630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 42730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o b = inode_bmap(inode, EXT2_IND_BLOCK); 428127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht b64 = b; 429127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht retval = ext2fs_alloc_block3(fs, b64, block_buf, &b64, 430127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht &alloc_ctx); 431127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht b = b64; 43230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (retval) 43330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o goto done; 43430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o inode_bmap(inode, EXT2_DIND_BLOCK) = b; 43530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o blocks_alloc++; 43630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 437efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o retval = block_dind_bmap(fs, bmap_flags, b, block_buf, 438cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o &blocks_alloc, block, &blk32); 439cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o if (retval == 0) 440cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o *phys_blk = blk32; 44130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o goto done; 44230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 44330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 44430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o /* Triply indirect block */ 44530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o block -= addr_per_block * addr_per_block; 44630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o b = inode_bmap(inode, EXT2_TIND_BLOCK); 44730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (!b) { 4481d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o if (!(bmap_flags & BMAP_ALLOC)) { 4491d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o if (bmap_flags & BMAP_SET) 4501d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o retval = EXT2_ET_SET_BMAP_NO_IND; 45130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o goto done; 4521d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o } 45330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 45430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o b = inode_bmap(inode, EXT2_DIND_BLOCK); 455127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht b64 = b; 456127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht retval = ext2fs_alloc_block3(fs, b64, block_buf, &b64, 457127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht &alloc_ctx); 458127a599529a0c31d8e3bc4da82a5debd670254b6Adrien Schildknecht b = b64; 45930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (retval) 46030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o goto done; 46130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o inode_bmap(inode, EXT2_TIND_BLOCK) = b; 46230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o blocks_alloc++; 46330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 464efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o retval = block_tind_bmap(fs, bmap_flags, b, block_buf, 465cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o &blocks_alloc, block, &blk32); 466cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o if (retval == 0) 467cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o *phys_blk = blk32; 46830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'odone: 46960a212f773ba116b4f7a9edb5eb76b40668ea8a0Darrick J. Wong if (*phys_blk && retval == 0 && (bmap_flags & BMAP_ZERO)) 47060a212f773ba116b4f7a9edb5eb76b40668ea8a0Darrick J. Wong retval = ext2fs_zero_blocks2(fs, *phys_blk, 1, NULL, NULL); 47130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (buf) 472c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&buf); 473cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o if (handle) 474cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o ext2fs_extent_free(handle); 4751d667534e93e78eedbf2efcef6d7844041675f26Theodore Ts'o if ((retval == 0) && (blocks_alloc || inode_dirty)) { 4761ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o ext2fs_iblk_add_blocks(fs, inode, blocks_alloc); 47730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o retval = ext2fs_write_inode(fs, ino, inode); 47830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 47930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o return retval; 48030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o} 48130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 482cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'oerrcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode, 483cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o char *block_buf, int bmap_flags, blk_t block, 484cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o blk_t *phys_blk) 485cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o{ 486cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o errcode_t ret; 4879c9e1d5fe507d08309e9815eee50ca73e21bd2bdTheodore Ts'o blk64_t ret_blk = *phys_blk; 488cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o 489cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o ret = ext2fs_bmap2(fs, ino, inode, block_buf, bmap_flags, block, 490cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o 0, &ret_blk); 491cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o if (ret) 492cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o return ret; 493cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o if (ret_blk >= ((long long) 1 << 32)) 494cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o return EOVERFLOW; 495cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o *phys_blk = ret_blk; 496cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o return 0; 497cc9bf5d246fc23267e14cc328728f146aee142e2Theodore Ts'o} 498