diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ext2fs/ChangeLog | 11 | ||||
-rw-r--r-- | lib/ext2fs/ext2fs.h | 11 | ||||
-rw-r--r-- | lib/ext2fs/initialize.c | 19 | ||||
-rw-r--r-- | lib/ext2fs/openfs.c | 11 |
4 files changed, 35 insertions, 17 deletions
diff --git a/lib/ext2fs/ChangeLog b/lib/ext2fs/ChangeLog index abd188f2..6a2c8bdf 100644 --- a/lib/ext2fs/ChangeLog +++ b/lib/ext2fs/ChangeLog @@ -1,3 +1,14 @@ +2006-08-30 Theodore Tso <tytso@mit.edu> + + * ext2fs.h (ext2fs_div_ceil): Add new function which safely + calculates an integer division where the result is always + rounded up while avoiding overflow errors. + + * initialize.c (calc_reserved_gdt_blocks, ext2fs_initialize): + * openfs.c (ext2fs_open2): Use ext2fs_div_ceil() instead of a + using an open-coded expression which was subject to + overflows. + 2006-08-06 Andreas Dilger <adilger@clusterfs.com> * bitops.h (ext2fs_cpu_to_le32, ext2fs_le64_to_cpu, diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index b3c2f656..8ca5723f 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -965,6 +965,7 @@ extern int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk); extern int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino); extern blk_t ext2fs_inode_data_blocks(ext2_filsys fs, struct ext2_inode *inode); +extern unsigned int ext2fs_div_ceil(unsigned int a, unsigned int b); /* * The actual inlined functions definitions themselves... @@ -1132,6 +1133,16 @@ _INLINE_ blk_t ext2fs_inode_data_blocks(ext2_filsys fs, return inode->i_blocks - (inode->i_file_acl ? fs->blocksize >> 9 : 0); } + +/* + * This is an efficient, overflow safe way of calculating ceil((1.0 * a) / b) + */ +_INLINE_ unsigned int ext2fs_div_ceil(unsigned int a, unsigned int b) +{ + if (!a) + return 0; + return ((a - 1) / b) + 1; +} #undef _INLINE_ #endif diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c index 05ba8c8a..6b476d98 100644 --- a/lib/ext2fs/initialize.c +++ b/lib/ext2fs/initialize.c @@ -77,8 +77,8 @@ static unsigned int calc_reserved_gdt_blocks(ext2_filsys fs) */ if (sb->s_blocks_count < max_blocks / 1024) max_blocks = sb->s_blocks_count * 1024; - rsv_groups = (max_blocks - sb->s_first_data_block + bpg - 1) / bpg; - rsv_gdb = (rsv_groups + gdpb - 1) / gdpb - fs->desc_blocks; + rsv_groups = ext2fs_div_ceil(max_blocks - sb->s_first_data_block, bpg); + rsv_gdb = ext2fs_div_ceil(rsv_groups, gdpb) - fs->desc_blocks; if (rsv_gdb > EXT2_ADDR_PER_BLOCK(sb)) rsv_gdb = EXT2_ADDR_PER_BLOCK(sb); #ifdef RES_GDT_DEBUG @@ -205,17 +205,15 @@ errcode_t ext2fs_initialize(const char *name, int flags, } retry: - fs->group_desc_count = (super->s_blocks_count - - super->s_first_data_block + - EXT2_BLOCKS_PER_GROUP(super) - 1) - / EXT2_BLOCKS_PER_GROUP(super); + fs->group_desc_count = ext2fs_div_ceil(super->s_blocks_count - + super->s_first_data_block, + EXT2_BLOCKS_PER_GROUP(super)); if (fs->group_desc_count == 0) { retval = EXT2_ET_TOOSMALL; goto cleanup; } - fs->desc_blocks = (fs->group_desc_count + - EXT2_DESC_PER_BLOCK(super) - 1) - / EXT2_DESC_PER_BLOCK(super); + fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count, + EXT2_DESC_PER_BLOCK(super)); i = fs->blocksize >= 4096 ? 1 : 4096 / fs->blocksize; set_field(s_inodes_count, super->s_blocks_count / i); @@ -233,8 +231,7 @@ retry: * should be. But make sure that we don't allocate more than * one bitmap's worth of inodes each group. */ - ipg = (super->s_inodes_count + fs->group_desc_count - 1) / - fs->group_desc_count; + ipg = ext2fs_div_ceil(super->s_inodes_count, fs->group_desc_count); if (ipg > fs->blocksize * 8) { if (super->s_blocks_per_group >= 256) { /* Try again with slightly different parameters */ diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c index 00149c80..f09484fc 100644 --- a/lib/ext2fs/openfs.c +++ b/lib/ext2fs/openfs.c @@ -258,12 +258,11 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, retval = EXT2_ET_CORRUPT_SUPERBLOCK; goto cleanup; } - fs->group_desc_count = (fs->super->s_blocks_count - - fs->super->s_first_data_block + - blocks_per_group - 1) / blocks_per_group; - fs->desc_blocks = (fs->group_desc_count + - EXT2_DESC_PER_BLOCK(fs->super) - 1) - / EXT2_DESC_PER_BLOCK(fs->super); + fs->group_desc_count = ext2fs_div_ceil(fs->super->s_blocks_count - + fs->super->s_first_data_block, + blocks_per_group); + fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count, + EXT2_DESC_PER_BLOCK(fs->super)); retval = ext2fs_get_mem(fs->desc_blocks * fs->blocksize, &fs->group_desc); if (retval) |