2009-08-05 14:34:31

by Aneesh Kumar K.V

[permalink] [raw]
Subject: [PATCH -V2 1/3] tune2fs: Make e2fsprogs handle ENOSPC better with inode resize

This removes the metadata block bitmap and makes the error handling
simpler. It also check for the enospc with the correct number needed
blocks. Also added specific error messages. We need to run e2undo
only if we start modyfing inode, group desc and inode table.

Signed-off-by: Aneesh Kumar K.V <[email protected]>
---
misc/tune2fs.c | 120 ++++++++++++++-----------------------------------------
1 files changed, 31 insertions(+), 89 deletions(-)

diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index 2ad3436..08fff29 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -962,34 +962,23 @@ static void parse_extended_opts(ext2_filsys fs, const char *opts)
}

/*
- * Fill in two bitmaps that we need to to control the inode resizing
- * process. The first is the set of blocks that must be moved, and
- * the second is the set of blocks which are allocation bitmap blocks
- * and must be treated specially.
+ * Fill in the block bitmap bmap with the information regarding the
+ * blocks to be moved
*/
static int get_move_bitmaps(ext2_filsys fs, int new_ino_blks_per_grp,
- ext2fs_block_bitmap bmap,
- ext2fs_block_bitmap metadata_bmap)
+ ext2fs_block_bitmap bmap)
{
dgrp_t i;
blk_t j, needed_blocks = 0;
- blk_t i_bmap, b_bmap;
blk_t start_blk, end_blk;
- int num, k;

for (i = 0; i < fs->group_desc_count; i++) {
- b_bmap = fs->group_desc[i].bg_block_bitmap;
- ext2fs_mark_block_bitmap(metadata_bmap, b_bmap);
- i_bmap = fs->group_desc[i].bg_inode_bitmap;
- ext2fs_mark_block_bitmap(metadata_bmap, i_bmap);
-
start_blk = fs->group_desc[i].bg_inode_table +
fs->inode_blocks_per_group;

end_blk = fs->group_desc[i].bg_inode_table +
new_ino_blks_per_grp;

- num=0;
for (j = start_blk; j < end_blk; j++) {
if (ext2fs_test_block_bitmap(fs->block_map, j)) {
/* FIXME!!
@@ -997,7 +986,6 @@ static int get_move_bitmaps(ext2_filsys fs, int new_ino_blks_per_grp,
* as a bad block
*/
ext2fs_mark_block_bitmap(bmap, j);
- needed_blocks++;
} else {
/*
* We are going to use this block for
@@ -1005,11 +993,8 @@ static int get_move_bitmaps(ext2_filsys fs, int new_ino_blks_per_grp,
*/
ext2fs_mark_block_bitmap(fs->block_map, j);
}
- if ((j == i_bmap) || (j == b_bmap))
- num++;
}
- if (num <= fs->group_desc[i].bg_free_blocks_count)
- continue;
+ needed_blocks += end_blk - start_blk;
}

if (needed_blocks > fs->super->s_free_blocks_count)
@@ -1018,14 +1003,12 @@ static int get_move_bitmaps(ext2_filsys fs, int new_ino_blks_per_grp,
return 0;
}

-static int move_block(ext2_filsys fs, ext2fs_block_bitmap bmap,
- ext2fs_block_bitmap metadata_bmap)
+static int move_block(ext2_filsys fs, ext2fs_block_bitmap bmap)
{
char *buf;
errcode_t retval;
blk_t blk, new_blk, goal;
struct blk_move *bmv;
- dgrp_t group;

retval = ext2fs_get_mem(fs->blocksize, &buf);
if (retval)
@@ -1036,16 +1019,7 @@ static int move_block(ext2_filsys fs, ext2fs_block_bitmap bmap,
if (!ext2fs_test_block_bitmap(bmap, blk))
continue;

- /*
- * If the block is a bitmap block, find a new block in
- * the same block group.
- */
- if (ext2fs_test_block_bitmap(metadata_bmap, blk)) {
- group = ext2fs_group_of_blk(fs, blk);
- goal = ext2fs_group_first_block(fs, group);
- } else
- goal = new_blk;
-
+ goal = new_blk;
retval = ext2fs_new_block(fs, goal, NULL, &new_blk);
if (retval)
goto err_out;
@@ -1184,37 +1158,6 @@ err_out:
return retval;
}

-/*
- * We need to scan for inode and block bitmaps that may need to be
- * moved. This can take place if the filesystem was formatted for
- * RAID arrays using the mke2fs's extended option "stride".
- */
-static int group_desc_scan_and_fix(ext2_filsys fs, ext2fs_block_bitmap bmap)
-{
- dgrp_t i;
- blk_t blk, new_blk;
-
- for (i = 0; i < fs->group_desc_count; i++) {
- blk = fs->group_desc[i].bg_block_bitmap;
- if (ext2fs_test_block_bitmap(bmap, blk)) {
- new_blk = translate_block(blk);
- if (!new_blk)
- continue;
- fs->group_desc[i].bg_block_bitmap = new_blk;
- }
-
- blk = fs->group_desc[i].bg_inode_bitmap;
- if (ext2fs_test_block_bitmap(bmap, blk)) {
- new_blk = translate_block(blk);
- if (!new_blk)
- continue;
- fs->group_desc[i].bg_inode_bitmap = new_blk;
- }
- }
- return 0;
-}
-
-
static int expand_inode_table(ext2_filsys fs, unsigned long new_ino_size)
{
dgrp_t i;
@@ -1367,7 +1310,7 @@ static int resize_inode(ext2_filsys fs, unsigned long new_size)
{
errcode_t retval;
int new_ino_blks_per_grp;
- ext2fs_block_bitmap bmap, metadata_bmap;
+ ext2fs_block_bitmap bmap;

ext2fs_read_inode_bitmap(fs);
ext2fs_read_block_bitmap(fs);
@@ -1387,34 +1330,28 @@ static int resize_inode(ext2_filsys fs, unsigned long new_size)

retval = ext2fs_allocate_block_bitmap(fs, _("blocks to be moved"),
&bmap);
- if (retval)
- return retval;
-
- retval = ext2fs_allocate_block_bitmap(fs, _("blocks to be moved"),
- &metadata_bmap);
- if (retval)
+ if (retval) {
+ fputs(_("Failed to allocate block bitmap when "
+ "increasing inode size\n"), stderr);
return retval;
-
- retval = get_move_bitmaps(fs, new_ino_blks_per_grp, bmap,
- metadata_bmap);
- if (retval)
+ }
+ retval = get_move_bitmaps(fs, new_ino_blks_per_grp, bmap);
+ if (retval) {
+ fputs(_("Not enough space to increase inode size \n"), stderr);
goto err_out;
-
- retval = move_block(fs, bmap, metadata_bmap);
- if (retval)
+ }
+ retval = move_block(fs, bmap);
+ if (retval) {
+ fputs(_("Failed to relocate blocks during inode resize \n"), stderr);
goto err_out;
-
+ }
retval = inode_scan_and_fix(fs, bmap);
if (retval)
- goto err_out;
-
- retval = group_desc_scan_and_fix(fs, bmap);
- if (retval)
- goto err_out;
+ goto err_out_undo;

retval = expand_inode_table(fs, new_size);
if (retval)
- goto err_out;
+ goto err_out_undo;

ext2fs_calculate_summary_stats(fs);

@@ -1428,6 +1365,15 @@ err_out:
ext2fs_free_block_bitmap(bmap);

return retval;
+
+err_out_undo:
+ free_blk_move_list();
+ ext2fs_free_block_bitmap(bmap);
+ fputs(_("Error in resizing the inode size.\n"
+ "Run e2undo to undo the "
+ "file system changes. \n"), stderr);
+
+ return retval;
}

static int tune2fs_setup_tdb(const char *name, io_manager *io_ptr)
@@ -1744,11 +1690,7 @@ retry_open:
* with the new free inode count
*/
fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
- if (resize_inode(fs, new_inode_size)) {
- fputs(_("Error in resizing the inode size.\n"
- "Run e2undo to undo the "
- "file system changes. \n"), stderr);
- } else {
+ if (resize_inode(fs, new_inode_size) == 0) {
printf(_("Setting inode size %lu\n"),
new_inode_size);
}
--
1.6.4.13.ge6580



2009-08-05 14:34:40

by Aneesh Kumar K.V

[permalink] [raw]
Subject: [PATCH -V2 2/3] tune2fs: Handle fs meta-data blocks during inode resize

With file system formated for RAID arrays we can have inode bitmap
and block bitmap after inode table. Make sure we move them around
properly when doing inode resize.

Signed-off-by: Aneesh Kumar K.V <[email protected]>
---
misc/tune2fs.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 82 insertions(+), 1 deletions(-)

diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index 08fff29..8c0b989 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -1003,10 +1003,39 @@ static int get_move_bitmaps(ext2_filsys fs, int new_ino_blks_per_grp,
return 0;
}

+static int ext2fs_is_meta_block(ext2_filsys fs, blk_t blk)
+{
+ dgrp_t group;
+ group = ext2fs_group_of_blk(fs, blk);
+ if (fs->group_desc[group].bg_block_bitmap == blk)
+ return 1;
+ if (fs->group_desc[group].bg_inode_bitmap == blk)
+ return 1;
+ return 0;
+}
+
+static int ext2fs_is_block_in_group(ext2_filsys fs, dgrp_t group, blk_t blk)
+{
+ blk_t start_blk, end_blk;
+ start_blk = fs->super->s_first_data_block +
+ EXT2_BLOCKS_PER_GROUP(fs->super) * group;
+ /*
+ * We cannot get new block beyond end_blk for for the last block group
+ * so we can check with EXT2_BLOCKS_PER_GROUP even for last block group
+ */
+ end_blk = start_blk + EXT2_BLOCKS_PER_GROUP(fs->super);
+ if (blk >= start_blk && blk <= end_blk)
+ return 1;
+ return 0;
+}
+
static int move_block(ext2_filsys fs, ext2fs_block_bitmap bmap)
{
+
char *buf;
+ dgrp_t group;
errcode_t retval;
+ int meta_data = 0;
blk_t blk, new_blk, goal;
struct blk_move *bmv;

@@ -1019,11 +1048,29 @@ static int move_block(ext2_filsys fs, ext2fs_block_bitmap bmap)
if (!ext2fs_test_block_bitmap(bmap, blk))
continue;

- goal = new_blk;
+ if (ext2fs_is_meta_block(fs, blk)) {
+ /*
+ * If the block is mapping a fs meta data block
+ * like group desc/block bitmap/inode bitmap. We
+ * should find a block in the same group and fix
+ * the respective fs metadata pointers. Otherwise
+ * fail
+ */
+ group = ext2fs_group_of_blk(fs, blk);
+ goal = ext2fs_group_first_block(fs, group);
+ meta_data = 1;
+
+ } else {
+ goal = new_blk;
+ }
retval = ext2fs_new_block(fs, goal, NULL, &new_blk);
if (retval)
goto err_out;

+ /* new fs meta data block should be in the same group */
+ if (meta_data && !ext2fs_is_block_in_group(fs, group, new_blk))
+ goto err_out;
+
/* Mark this block as allocated */
ext2fs_mark_block_bitmap(fs->block_map, new_blk);

@@ -1158,6 +1205,36 @@ err_out:
return retval;
}

+/*
+ * We need to scan for inode and block bitmaps that may need to be
+ * moved. This can take place if the filesystem was formatted for
+ * RAID arrays using the mke2fs's extended option "stride".
+ */
+static int group_desc_scan_and_fix(ext2_filsys fs, ext2fs_block_bitmap bmap)
+{
+ dgrp_t i;
+ blk_t blk, new_blk;
+
+ for (i = 0; i < fs->group_desc_count; i++) {
+ blk = fs->group_desc[i].bg_block_bitmap;
+ if (ext2fs_test_block_bitmap(bmap, blk)) {
+ new_blk = translate_block(blk);
+ if (!new_blk)
+ continue;
+ fs->group_desc[i].bg_block_bitmap = new_blk;
+ }
+
+ blk = fs->group_desc[i].bg_inode_bitmap;
+ if (ext2fs_test_block_bitmap(bmap, blk)) {
+ new_blk = translate_block(blk);
+ if (!new_blk)
+ continue;
+ fs->group_desc[i].bg_inode_bitmap = new_blk;
+ }
+ }
+ return 0;
+}
+
static int expand_inode_table(ext2_filsys fs, unsigned long new_ino_size)
{
dgrp_t i;
@@ -1349,6 +1426,10 @@ static int resize_inode(ext2_filsys fs, unsigned long new_size)
if (retval)
goto err_out_undo;

+ retval = group_desc_scan_and_fix(fs, bmap);
+ if (retval)
+ goto err_out_undo;
+
retval = expand_inode_table(fs, new_size);
if (retval)
goto err_out_undo;
--
1.6.4.13.ge6580


2009-08-05 14:34:47

by Aneesh Kumar K.V

[permalink] [raw]
Subject: [PATCH -V2 3/3] tune2fs: handle bad blocks when resizing inodes

When increasing inode size if we find that the new block
that we needed to increase the inode table size is a bad
block we fail. This make sure we don't end up with a corrupt
file system when doing inode resize on a file system having
bad blocks.

Signed-off-by: Aneesh Kumar K.V <[email protected]>
---
misc/tune2fs.c | 17 ++++++++++++++---
1 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index 8c0b989..8b7161b 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -969,9 +969,15 @@ static int get_move_bitmaps(ext2_filsys fs, int new_ino_blks_per_grp,
ext2fs_block_bitmap bmap)
{
dgrp_t i;
+ int retval;
+ ext2_badblocks_list bb_list = 0;
blk_t j, needed_blocks = 0;
blk_t start_blk, end_blk;

+ retval = ext2fs_read_bb_inode(fs, &bb_list);
+ if (retval)
+ return retval;
+
for (i = 0; i < fs->group_desc_count; i++) {
start_blk = fs->group_desc[i].bg_inode_table +
fs->inode_blocks_per_group;
@@ -981,10 +987,14 @@ static int get_move_bitmaps(ext2_filsys fs, int new_ino_blks_per_grp,

for (j = start_blk; j < end_blk; j++) {
if (ext2fs_test_block_bitmap(fs->block_map, j)) {
- /* FIXME!!
- * What happens if the block is marked
- * as a bad block
+ /*
+ * IF the block is a bad block we fail
*/
+ if (ext2fs_badblocks_list_test(bb_list, j)) {
+ ext2fs_badblocks_list_free(bb_list);
+ return ENOSPC;
+ }
+
ext2fs_mark_block_bitmap(bmap, j);
} else {
/*
@@ -997,6 +1007,7 @@ static int get_move_bitmaps(ext2_filsys fs, int new_ino_blks_per_grp,
needed_blocks += end_blk - start_blk;
}

+ ext2fs_badblocks_list_free(bb_list);
if (needed_blocks > fs->super->s_free_blocks_count)
return ENOSPC;

--
1.6.4.13.ge6580