* grub-core/fs/ext2.c (grub_ext2_read_block): Factor out common code for indirect block handling.

Saves 185 bytes on compressed image.
This commit is contained in:
Colin Watson 2013-11-14 08:13:06 +00:00
parent e6050a683c
commit 5da5517288
2 changed files with 44 additions and 80 deletions

View file

@ -1,3 +1,10 @@
2013-11-14 Colin Watson <cjwatson@ubuntu.com>
* grub-core/fs/ext2.c (grub_ext2_read_block): Factor out common
code for indirect block handling.
Saves 185 bytes on compressed image.
2013-11-13 Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com> 2013-11-13 Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
Fix make clean. Fix make clean.

View file

@ -397,9 +397,12 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{ {
struct grub_ext2_data *data = node->data; struct grub_ext2_data *data = node->data;
struct grub_ext2_inode *inode = &node->inode; struct grub_ext2_inode *inode = &node->inode;
grub_disk_addr_t blknr = -1;
unsigned int blksz = EXT2_BLOCK_SIZE (data); unsigned int blksz = EXT2_BLOCK_SIZE (data);
grub_disk_addr_t blksz_quarter = blksz / 4;
int log2_blksz = LOG2_EXT2_BLOCK_SIZE (data); int log2_blksz = LOG2_EXT2_BLOCK_SIZE (data);
int log_perblock = log2_blksz + 9 - 2;
grub_uint32_t indir;
int shift;
if (inode->flags & grub_cpu_to_le32_compile_time (EXT4_EXTENTS_FLAG)) if (inode->flags & grub_cpu_to_le32_compile_time (EXT4_EXTENTS_FLAG))
{ {
@ -448,96 +451,50 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
return ret; return ret;
} }
/* Direct blocks. */ /* Direct blocks. */
if (fileblock < INDIRECT_BLOCKS) if (fileblock < INDIRECT_BLOCKS)
blknr = grub_le_to_cpu32 (inode->blocks.dir_blocks[fileblock]); return grub_le_to_cpu32 (inode->blocks.dir_blocks[fileblock]);
fileblock -= INDIRECT_BLOCKS;
/* Indirect. */ /* Indirect. */
else if (fileblock < INDIRECT_BLOCKS + blksz / 4) if (fileblock < blksz_quarter)
{ {
grub_uint32_t indir; indir = inode->blocks.indir_block;
shift = 0;
if (grub_disk_read (data->disk, goto indirect;
((grub_disk_addr_t)
grub_le_to_cpu32 (inode->blocks.indir_block))
<< log2_blksz,
(fileblock - INDIRECT_BLOCKS) * sizeof (indir),
sizeof (indir), &indir))
return grub_errno;
blknr = grub_le_to_cpu32 (indir);
} }
fileblock -= blksz_quarter;
/* Double indirect. */ /* Double indirect. */
else if (fileblock < INDIRECT_BLOCKS if (fileblock < blksz_quarter * blksz_quarter)
+ blksz / 4 * ((grub_disk_addr_t) blksz / 4 + 1))
{ {
int log_perblock = log2_blksz + 9 - 2; indir = inode->blocks.double_indir_block;
grub_disk_addr_t rblock = fileblock - (INDIRECT_BLOCKS shift = 1;
+ blksz / 4); goto indirect;
grub_uint32_t indir;
if (grub_disk_read (data->disk,
((grub_disk_addr_t)
grub_le_to_cpu32 (inode->blocks.double_indir_block))
<< log2_blksz,
(rblock >> log_perblock) * sizeof (indir),
sizeof (indir), &indir))
return grub_errno;
if (grub_disk_read (data->disk,
((grub_disk_addr_t)
grub_le_to_cpu32 (indir))
<< log2_blksz,
(rblock & ((1 << log_perblock) - 1)) * sizeof (indir),
sizeof (indir), &indir))
return grub_errno;
blknr = grub_le_to_cpu32 (indir);
} }
/* triple indirect. */ fileblock -= blksz_quarter * blksz_quarter;
else if (fileblock < INDIRECT_BLOCKS + blksz / 4 * ((grub_disk_addr_t) blksz / 4 + 1) /* Triple indirect. */
+ ((grub_disk_addr_t) blksz / 4) * ((grub_disk_addr_t) blksz / 4) if (fileblock < blksz_quarter * blksz_quarter * (blksz_quarter + 1))
* ((grub_disk_addr_t) blksz / 4 + 1))
{ {
int log_perblock = log2_blksz + 9 - 2; indir = inode->blocks.triple_indir_block;
grub_disk_addr_t rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4 shift = 2;
* (blksz / 4 + 1)); goto indirect;
grub_uint32_t indir;
if (grub_disk_read (data->disk,
((grub_disk_addr_t)
grub_le_to_cpu32 (inode->blocks.triple_indir_block))
<< log2_blksz,
((rblock >> log_perblock) >> log_perblock)
* sizeof (indir), sizeof (indir), &indir))
return grub_errno;
if (grub_disk_read (data->disk,
((grub_disk_addr_t)
grub_le_to_cpu32 (indir))
<< log2_blksz,
((rblock >> log_perblock)
& ((1 << log_perblock) - 1)) * sizeof (indir),
sizeof (indir), &indir))
return grub_errno;
if (grub_disk_read (data->disk,
((grub_disk_addr_t)
grub_le_to_cpu32 (indir))
<< log2_blksz,
(rblock & ((1 << log_perblock) - 1))
* sizeof (indir), sizeof (indir), &indir))
return grub_errno;
blknr = grub_le_to_cpu32 (indir);
}
else
{
grub_error (GRUB_ERR_BAD_FS,
"ext2fs doesn't support quadruple indirect blocks");
} }
return grub_error (GRUB_ERR_BAD_FS,
"ext2fs doesn't support quadruple indirect blocks");
return blknr; indirect:
do {
if (grub_disk_read (data->disk,
((grub_disk_addr_t) grub_le_to_cpu32 (indir))
<< log2_blksz,
((fileblock >> (log_perblock * shift))
& ((1 << log_perblock) - 1))
* sizeof (indir),
sizeof (indir), &indir))
return grub_errno;
} while (shift--);
return grub_le_to_cpu32 (indir);
} }
/* Read LEN bytes from the file described by DATA starting with byte /* Read LEN bytes from the file described by DATA starting with byte