Fix ext2/ext4 filesystem accesses beyond 2TiB
With CONFIG_SYS_64BIT_LBA, lbaint_t gets defined as a 64-bit type,
which is required to represent block numbers for storage devices that
exceed 2TiB (the block size usually is 512B), e.g. recent hard drives
We now use lbaint_t for partition offset to reflect the lbaint_t change,
and access partitions beyond or crossing the 2.1TiB limit.
This required changes to signature of ext4fs_devread(), and type of all
variables relatives to block sector.
ext2/ext4 fs uses logical block represented by a 32 bit value. Logical
block is a multiple of device block sector. To avoid overflow problem
when calling ext4fs_devread(), we need to cast the sector parameter.
Signed-off-by: Frédéric Leroy <fredo@starox.org>
diff --git a/fs/ext4/ext4_write.c b/fs/ext4/ext4_write.c
index 0c1f62b..501b95a 100644
--- a/fs/ext4/ext4_write.c
+++ b/fs/ext4/ext4_write.c
@@ -88,8 +88,8 @@
if (!fs->gdtable)
return -ENOMEM;
/* read the group descriptor table */
- status = ext4fs_devread(fs->gdtable_blkno * fs->sect_perblk, 0,
- fs->blksz * fs->no_blk_pergdt, fs->gdtable);
+ status = ext4fs_devread((lbaint_t)fs->gdtable_blkno * fs->sect_perblk,
+ 0, fs->blksz * fs->no_blk_pergdt, fs->gdtable);
if (status == 0)
goto fail;
@@ -142,7 +142,7 @@
/* journal backup */
if (prev_bg_bmap_idx != bg_idx) {
status =
- ext4fs_devread(bgd[bg_idx].block_id *
+ ext4fs_devread((lbaint_t)bgd[bg_idx].block_id *
fs->sect_perblk, 0, fs->blksz,
journal_buffer);
if (status == 0)
@@ -186,8 +186,8 @@
}
DIB_start_addr = (unsigned int *)di_buffer;
blknr = inode->b.blocks.double_indir_block;
- status = ext4fs_devread(blknr * fs->sect_perblk, 0, fs->blksz,
- (char *)di_buffer);
+ status = ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
+ fs->blksz, (char *)di_buffer);
for (i = 0; i < fs->blksz / sizeof(int); i++) {
if (*di_buffer == 0)
break;
@@ -208,7 +208,8 @@
fs->sb->free_blocks++;
/* journal backup */
if (prev_bg_bmap_idx != bg_idx) {
- status = ext4fs_devread(bgd[bg_idx].block_id
+ status = ext4fs_devread((lbaint_t)
+ bgd[bg_idx].block_id
* fs->sect_perblk, 0,
fs->blksz,
journal_buffer);
@@ -238,7 +239,7 @@
/* journal backup */
if (prev_bg_bmap_idx != bg_idx) {
memset(journal_buffer, '\0', fs->blksz);
- status = ext4fs_devread(bgd[bg_idx].block_id *
+ status = ext4fs_devread((lbaint_t)bgd[bg_idx].block_id *
fs->sect_perblk, 0, fs->blksz,
journal_buffer);
if (status == 0)
@@ -287,8 +288,8 @@
}
tib_start_addr = (unsigned int *)tigp_buffer;
blknr = inode->b.blocks.triple_indir_block;
- status = ext4fs_devread(blknr * fs->sect_perblk, 0, fs->blksz,
- (char *)tigp_buffer);
+ status = ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
+ fs->blksz, (char *)tigp_buffer);
for (i = 0; i < fs->blksz / sizeof(int); i++) {
if (*tigp_buffer == 0)
break;
@@ -298,7 +299,7 @@
if (!tip_buffer)
goto fail;
tipb_start_addr = (unsigned int *)tip_buffer;
- status = ext4fs_devread((*tigp_buffer) *
+ status = ext4fs_devread((lbaint_t)(*tigp_buffer) *
fs->sect_perblk, 0, fs->blksz,
(char *)tip_buffer);
for (j = 0; j < fs->blksz / sizeof(int); j++) {
@@ -325,6 +326,7 @@
if (prev_bg_bmap_idx != bg_idx) {
status =
ext4fs_devread(
+ (lbaint_t)
bgd[bg_idx].block_id *
fs->sect_perblk, 0,
fs->blksz,
@@ -365,7 +367,8 @@
if (prev_bg_bmap_idx != bg_idx) {
memset(journal_buffer, '\0', fs->blksz);
status =
- ext4fs_devread(bgd[bg_idx].block_id *
+ ext4fs_devread((lbaint_t)
+ bgd[bg_idx].block_id *
fs->sect_perblk, 0,
fs->blksz, journal_buffer);
if (status == 0)
@@ -394,7 +397,7 @@
/* journal backup */
if (prev_bg_bmap_idx != bg_idx) {
memset(journal_buffer, '\0', fs->blksz);
- status = ext4fs_devread(bgd[bg_idx].block_id *
+ status = ext4fs_devread((lbaint_t)bgd[bg_idx].block_id *
fs->sect_perblk, 0, fs->blksz,
journal_buffer);
if (status == 0)
@@ -480,7 +483,8 @@
/* journal backup */
if (prev_bg_bmap_idx != bg_idx) {
status =
- ext4fs_devread(bgd[bg_idx].block_id *
+ ext4fs_devread((lbaint_t)
+ bgd[bg_idx].block_id *
fs->sect_perblk, 0,
fs->blksz, journal_buffer);
if (status == 0)
@@ -524,7 +528,8 @@
/* journal backup */
if (prev_bg_bmap_idx != bg_idx) {
memset(journal_buffer, '\0', fs->blksz);
- status = ext4fs_devread(bgd[bg_idx].block_id
+ status = ext4fs_devread((lbaint_t)
+ bgd[bg_idx].block_id
* fs->sect_perblk,
0, fs->blksz,
journal_buffer);
@@ -555,7 +560,7 @@
if (!read_buffer)
goto fail;
start_block_address = read_buffer;
- status = ext4fs_devread(blkno * fs->sect_perblk,
+ status = ext4fs_devread((lbaint_t)blkno * fs->sect_perblk,
0, fs->blksz, read_buffer);
if (status == 0)
goto fail;
@@ -578,7 +583,7 @@
fs->sb->free_inodes++;
/* journal backup */
memset(journal_buffer, '\0', fs->blksz);
- status = ext4fs_devread(bgd[ibmap_idx].inode_id *
+ status = ext4fs_devread((lbaint_t)bgd[ibmap_idx].inode_id *
fs->sect_perblk, 0, fs->blksz, journal_buffer);
if (status == 0)
goto fail;
@@ -653,7 +658,8 @@
for (i = 0; i < fs->no_blkgrp; i++) {
status =
- ext4fs_devread(fs->bgd[i].block_id * fs->sect_perblk, 0,
+ ext4fs_devread((lbaint_t)fs->bgd[i].block_id *
+ fs->sect_perblk, 0,
fs->blksz, (char *)fs->blk_bmaps[i]);
if (status == 0)
goto fail;
@@ -670,7 +676,8 @@
}
for (i = 0; i < fs->no_blkgrp; i++) {
- status = ext4fs_devread(fs->bgd[i].inode_id * fs->sect_perblk,
+ status = ext4fs_devread((lbaint_t)fs->bgd[i].inode_id *
+ fs->sect_perblk,
0, fs->blksz,
(char *)fs->inode_bmaps[i]);
if (status == 0)
@@ -710,7 +717,7 @@
&inode_journal);
blknr = read_allocated_block(&inode_journal,
EXT2_JOURNAL_SUPERBLOCK);
- ext4fs_devread(blknr * fs->sect_perblk, 0, fs->blksz,
+ ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0, fs->blksz,
temp_buff);
jsb = (struct journal_superblock_t *)temp_buff;
jsb->s_start = cpu_to_be32(0);
@@ -934,7 +941,8 @@
(inodeno % __le32_to_cpu(sblock->inodes_per_group)) /
inodes_per_block;
blkoff = (inodeno % inodes_per_block) * fs->inodesz;
- ext4fs_devread(itable_blkno * fs->sect_perblk, 0, fs->blksz, temp_ptr);
+ ext4fs_devread((lbaint_t)itable_blkno * fs->sect_perblk, 0, fs->blksz,
+ temp_ptr);
if (ext4fs_log_journal(temp_ptr, itable_blkno))
goto fail;
@@ -954,7 +962,7 @@
blkoff = (parent_inodeno % inodes_per_block) * fs->inodesz;
if (parent_itable_blkno != itable_blkno) {
memset(temp_ptr, '\0', fs->blksz);
- ext4fs_devread(parent_itable_blkno * fs->sect_perblk,
+ ext4fs_devread((lbaint_t)parent_itable_blkno * fs->sect_perblk,
0, fs->blksz, temp_ptr);
if (ext4fs_log_journal(temp_ptr, parent_itable_blkno))
goto fail;