From 04735e9c5578dd4f3584be5454b9779e8e5c2af9 Mon Sep 17 00:00:00 2001 From: Frederic Leroy Date: Wed, 26 Jun 2013 18:11:25 +0200 Subject: Fix ext2/ext4 filesystem accesses beyond 2TiB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- fs/ext4/ext4_write.c | 50 +++++++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 21 deletions(-) (limited to 'fs/ext4/ext4_write.c') diff --git a/fs/ext4/ext4_write.c b/fs/ext4/ext4_write.c index 0c1f62b60c..501b95ab7d 100644 --- a/fs/ext4/ext4_write.c +++ b/fs/ext4/ext4_write.c @@ -88,8 +88,8 @@ int ext4fs_get_bgdtable(void) 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 @@ static void delete_single_indirect_block(struct ext2_inode *inode) /* 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 @@ static void delete_double_indirect_block(struct ext2_inode *inode) } 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 @@ static void delete_double_indirect_block(struct ext2_inode *inode) 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 @@ static void delete_double_indirect_block(struct ext2_inode *inode) /* 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 @@ static void delete_triple_indirect_block(struct ext2_inode *inode) } 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 @@ static void delete_triple_indirect_block(struct ext2_inode *inode) 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 @@ static void delete_triple_indirect_block(struct ext2_inode *inode) 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 @@ static void delete_triple_indirect_block(struct ext2_inode *inode) 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 @@ static void delete_triple_indirect_block(struct ext2_inode *inode) /* 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 @@ static int ext4fs_delete_file(int inodeno) /* 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 @@ static int ext4fs_delete_file(int inodeno) /* 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 @@ static int ext4fs_delete_file(int inodeno) 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 @@ static int ext4fs_delete_file(int inodeno) 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 @@ int ext4fs_init(void) 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 @@ int ext4fs_init(void) } 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 @@ void ext4fs_deinit(void) &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 @@ int ext4fs_write(const char *fname, unsigned char *buffer, (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 @@ int ext4fs_write(const char *fname, unsigned char *buffer, 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; -- cgit v1.2.3