summaryrefslogtreecommitdiff
path: root/lib/ext2fs
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2011-07-07 22:27:42 -0400
committerTheodore Ts'o <tytso@mit.edu>2011-07-07 22:27:42 -0400
commit8e8a190fa212ca28efb2e8a8b3318a24d7fc4b7a (patch)
treed751acc9810259e1c323edeed8ad45a80b3fe6a8 /lib/ext2fs
parent551e2e46ee2fdf8cfa16e153d3c560203f0f9a5e (diff)
downloade2fsprogs-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>
Diffstat (limited to 'lib/ext2fs')
-rw-r--r--lib/ext2fs/bmap.c46
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;