]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
libext2fs: teach ext2fs_bmap2() about bigalloc
authorTheodore Ts'o <tytso@mit.edu>
Fri, 8 Jul 2011 02:27:42 +0000 (22:27 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Fri, 8 Jul 2011 02:27:42 +0000 (22:27 -0400)
This allows debugfs's write command to work correctly on bigalloc file
systems.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
lib/ext2fs/bmap.c

index f3e41c26f0333b0038e2a85de1713b4fd49d3150..7a515be490e82928910da15ce893301f71417864 100644 (file)
@@ -129,6 +129,40 @@ static _BMAP_INLINE_ errcode_t block_tind_bmap(ext2_filsys fs, int flags,
        return retval;
 }
 
+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);
+
+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,
@@ -139,7 +173,8 @@ static errcode_t extent_bmap(ext2_filsys fs, ext2_ino_t ino,
        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;