diff options
author | Theodore Ts'o <tytso@mit.edu> | 2011-07-07 22:27:42 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2011-07-07 22:27:42 -0400 |
commit | 8e8a190fa212ca28efb2e8a8b3318a24d7fc4b7a (patch) | |
tree | d751acc9810259e1c323edeed8ad45a80b3fe6a8 | |
parent | 551e2e46ee2fdf8cfa16e153d3c560203f0f9a5e (diff) | |
download | e2fsprogs-8e8a190fa212ca28efb2e8a8b3318a24d7fc4b7a.tar.gz |
libext2fs: teach ext2fs_bmap2() about bigalloc
This allows debugfs's write command to work correctly on bigalloc file
systems.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
-rw-r--r-- | lib/ext2fs/bmap.c | 46 |
1 files changed, 44 insertions, 2 deletions
diff --git a/lib/ext2fs/bmap.c b/lib/ext2fs/bmap.c index f3e41c26..7a515be4 100644 --- a/lib/ext2fs/bmap.c +++ b/lib/ext2fs/bmap.c @@ -134,12 +134,47 @@ static errcode_t extent_bmap(ext2_filsys fs, ext2_ino_t ino, ext2_extent_handle_t handle, char *block_buf, int bmap_flags, blk64_t block, int *ret_flags, int *blocks_alloc, + blk64_t *phys_blk); + +static errcode_t implied_cluster_alloc(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + ext2_extent_handle_t handle, + blk64_t block, blk64_t *phys_blk) +{ + blk64_t base_block, pblock = 0; + int i; + + if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, + EXT4_FEATURE_RO_COMPAT_BIGALLOC)) + return 0; + + base_block = block & ~EXT2FS_CLUSTER_MASK(fs); + for (i = 0; i < EXT2FS_CLUSTER_RATIO(fs); i++) { + if (block == base_block) + return 0; + extent_bmap(fs, ino, inode, handle, 0, 0, + base_block + i, 0, 0, &pblock); + if (pblock) + break; + } + if (pblock == 0) + return 0; + *phys_blk = pblock - i + (block - base_block); + return 0; +} + +static errcode_t extent_bmap(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + ext2_extent_handle_t handle, + char *block_buf, int bmap_flags, blk64_t block, + int *ret_flags, int *blocks_alloc, blk64_t *phys_blk) { struct ext2fs_extent extent; unsigned int offset; errcode_t retval = 0; - blk64_t blk64; + blk64_t blk64 = 0; + int alloc = 0; if (bmap_flags & BMAP_SET) { retval = ext2fs_extent_set_bmap(handle, block, @@ -164,6 +199,9 @@ static errcode_t extent_bmap(ext2_filsys fs, ext2_ino_t ino, } got_block: if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) { + implied_cluster_alloc(fs, ino, inode, handle, block, &blk64); + if (blk64) + goto set_extent; retval = extent_bmap(fs, ino, inode, handle, block_buf, 0, block-1, 0, blocks_alloc, &blk64); if (retval) @@ -172,6 +210,10 @@ got_block: &blk64); if (retval) return retval; + blk64 &= ~EXT2FS_CLUSTER_MASK(fs); + blk64 += EXT2FS_CLUSTER_MASK(fs) & block; + alloc++; + set_extent: retval = ext2fs_extent_set_bmap(handle, block, blk64, 0); if (retval) @@ -180,7 +222,7 @@ got_block: retval = ext2fs_read_inode(fs, ino, inode); if (retval) return retval; - *blocks_alloc += 1; + *blocks_alloc += alloc; *phys_blk = blk64; } return 0; |