[U-Boot] [PATCH v2 0/4] Add Support for Storage Devices with Blocksizes != 512

From: Egbert Eich eich@suse.de
Storage devices with more than 2TB generally use blocksizes of 4096 bytes, So far u-boot was unable to boot from those devices as block sizes were hard coded to 512 bytes.
This patchset adds support for blocksizes != 512 byte to: - the ISO partition table. - the ext4.
To be useful, one most likely needs: "disk/gpt: Fix GPT Partition handling for Blocksize != 512" which was posted earlier.
With those fixes in place u-boot loads the kernel and initrd flawlessly from an ext2 fs on my 3TB USB hard drive which is set up with a GPT.
I've also reviewed the FAT code, it seems to be ok already (except for a bug that I came across).
I may be persuaded to take a shot at other fs which are supported by a vanilla Linux kernel and I thus can test.
Egbert Eich (4): disk/iso: Add Support for block sizes > 512 byte to ISO partition support fs/fat: Don't multiply fatsize with sector size part/dev_desc: Add log2 of blocksize to block_dev_desc data struct fs/ext4: Support device block sizes != 512 bytes
common/cmd_ide.c | 5 ++++ common/cmd_sata.c | 1 + common/cmd_scsi.c | 4 +++ common/usb_storage.c | 1 + disk/part_iso.c | 3 +++ drivers/block/ata_piix.c | 1 + drivers/block/pata_bfin.c | 2 ++ drivers/block/systemace.c | 1 + drivers/mmc/mmc.c | 1 + fs/ext4/dev.c | 62 ++++++++++++++++++++++++++++++----------------- fs/ext4/ext4_common.c | 42 +++++++++++++++++--------------- fs/ext4/ext4_common.h | 2 +- fs/ext4/ext4_journal.c | 6 ++--- fs/ext4/ext4_write.c | 32 ++++++++++++------------ fs/ext4/ext4fs.c | 14 ++++++----- fs/fat/fat_write.c | 1 - include/common.h | 2 +- include/ext4fs.h | 1 + include/ext_common.h | 12 +++------ include/part.h | 5 ++++ 20 files changed, 120 insertions(+), 78 deletions(-)

From: Egbert Eich eich@suse.com
For ISO we check the block size of the device if this is != the CD sector size we assume that the device has no ISO partition.
Signed-off-by: Egbert Eich eich@suse.com --- Changes for v2: - Coding style fixes.
disk/part_iso.c | 3 +++ include/common.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/disk/part_iso.c b/disk/part_iso.c index 49639af..cc323b0 100644 --- a/disk/part_iso.c +++ b/disk/part_iso.c @@ -73,6 +73,9 @@ int get_partition_info_iso_verb(block_dev_desc_t * dev_desc, int part_num, disk_ iso_val_entry_t *pve = (iso_val_entry_t *)tmpbuf; iso_init_def_entry_t *pide;
+ if (dev_desc->blksz != CD_SECTSIZE) + return -1; + /* the first sector (sector 0x10) must be a primary volume desc */ blkaddr=PVD_OFFSET; if (dev_desc->block_read (dev_desc->dev, PVD_OFFSET, 1, (ulong *) tmpbuf) != 1) diff --git a/include/common.h b/include/common.h index 53cc859..c080cb8 100644 --- a/include/common.h +++ b/include/common.h @@ -1011,7 +1011,7 @@ static inline void unmap_sysmem(const void *vaddr) */ #define DEFINE_ALIGN_BUFFER(type, name, size, align) \ static char __##name[roundup(size * sizeof(type), align)] \ - __attribute__((aligned(align))); \ + __aligned(align); \ \ static type *name = (type *)__##name #define DEFINE_CACHE_ALIGN_BUFFER(type, name, size) \

On Tue, Apr 09, 2013 at 09:11:54PM -0000, egbert.eich@gmail.com wrote:
From: Egbert Eich eich@suse.com
For ISO we check the block size of the device if this is != the CD sector size we assume that the device has no ISO partition.
Signed-off-by: Egbert Eich eich@suse.com
Applied to u-boot/master, thanks!

From: Egbert Eich eich@suse.com
Bugfix: Here at this place we need the fat size in sectors not bytes. This was found during code review when adding support for storage devices with blocksizes != 512.
Signed-off-by: Egbert Eich eich@suse.com --- Changes for v2: - Coding style fixes.
fs/fat/fat_write.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c index b4022aa..fd07240 100644 --- a/fs/fat/fat_write.c +++ b/fs/fat/fat_write.c @@ -120,7 +120,6 @@ static int flush_fat_buffer(fsdata *mydata) __u8 *bufptr = mydata->fatbuf; __u32 startblock = mydata->fatbufnum * FATBUFBLOCKS;
- fatlength *= mydata->sect_size; startblock += mydata->fat_sect;
if (getsize > fatlength)

On Tue, Apr 09, 2013 at 09:11:55PM -0000, egbert.eich@gmail.com wrote:
From: Egbert Eich eich@suse.com
Bugfix: Here at this place we need the fat size in sectors not bytes. This was found during code review when adding support for storage devices with blocksizes != 512.
Signed-off-by: Egbert Eich eich@suse.com
Applied to u-boot/master, thanks!

From: Egbert Eich eich@suse.com
log2 of the device block size serves as the shift value used to calculate the block number to read in file systems when implementing avaiable block sizes. It is needed quite often in file systems thus it is pre-calculated and stored in the block device descriptor.
Signed-off-by: Egbert Eich eich@suse.com --- Changes for v2: - Coding style fixes.
common/cmd_ide.c | 5 +++++ common/cmd_sata.c | 1 + common/cmd_scsi.c | 4 ++++ common/usb_storage.c | 1 + drivers/block/ata_piix.c | 1 + drivers/block/pata_bfin.c | 2 ++ drivers/block/systemace.c | 1 + drivers/mmc/mmc.c | 1 + include/part.h | 5 +++++ 9 files changed, 21 insertions(+)
diff --git a/common/cmd_ide.c b/common/cmd_ide.c index 0105bdb..78b4aa7 100644 --- a/common/cmd_ide.c +++ b/common/cmd_ide.c @@ -455,6 +455,8 @@ void ide_init(void) ide_dev_desc[i].dev = i; ide_dev_desc[i].part_type = PART_TYPE_UNKNOWN; ide_dev_desc[i].blksz = 0; + ide_dev_desc[i].log2blksz = + LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz)); ide_dev_desc[i].lba = 0; ide_dev_desc[i].block_read = ide_read; ide_dev_desc[i].block_write = ide_write; @@ -806,6 +808,7 @@ static void ide_ident(block_dev_desc_t *dev_desc) /* assuming HD */ dev_desc->type = DEV_TYPE_HARDDISK; dev_desc->blksz = ATA_BLOCKSIZE; + dev_desc->log2blksz = LOG2(dev_desc->blksz); dev_desc->lun = 0; /* just to fill something in... */
#if 0 /* only used to test the powersaving mode, @@ -1448,6 +1451,7 @@ static void atapi_inquiry(block_dev_desc_t *dev_desc) dev_desc->lun = 0; dev_desc->lba = 0; dev_desc->blksz = 0; + dev_desc->log2blksz = LOG2_INVALID(typeof(dev_desc->log2blksz)); dev_desc->type = iobuf[0] & 0x1f;
if ((iobuf[1] & 0x80) == 0x80) @@ -1492,6 +1496,7 @@ static void atapi_inquiry(block_dev_desc_t *dev_desc) dev_desc->blksz = ((unsigned long) iobuf[4] << 24) + ((unsigned long) iobuf[5] << 16) + ((unsigned long) iobuf[6] << 8) + ((unsigned long) iobuf[7]); + dev_desc->log2blksz = LOG2(dev_desc->blksz); #ifdef CONFIG_LBA48 /* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */ dev_desc->lba48 = 0; diff --git a/common/cmd_sata.c b/common/cmd_sata.c index 8d57285..5a57a37 100644 --- a/common/cmd_sata.c +++ b/common/cmd_sata.c @@ -44,6 +44,7 @@ int __sata_initialize(void) sata_dev_desc[i].type = DEV_TYPE_HARDDISK; sata_dev_desc[i].lba = 0; sata_dev_desc[i].blksz = 512; + sata_dev_desc[i].log2blksz = LOG2(sata_dev_desc[i].blksz); sata_dev_desc[i].block_read = sata_read; sata_dev_desc[i].block_write = sata_write;
diff --git a/common/cmd_scsi.c b/common/cmd_scsi.c index 13b3d99..294d9f5 100644 --- a/common/cmd_scsi.c +++ b/common/cmd_scsi.c @@ -106,6 +106,8 @@ void scsi_scan(int mode) scsi_dev_desc[i].lun=0xff; scsi_dev_desc[i].lba=0; scsi_dev_desc[i].blksz=0; + scsi_dev_desc[i].log2blksz = + LOG2_INVALID(typeof(scsi_dev_desc[i].log2blksz)); scsi_dev_desc[i].type=DEV_TYPE_UNKNOWN; scsi_dev_desc[i].vendor[0]=0; scsi_dev_desc[i].product[0]=0; @@ -166,6 +168,8 @@ void scsi_scan(int mode) } scsi_dev_desc[scsi_max_devs].lba=capacity; scsi_dev_desc[scsi_max_devs].blksz=blksz; + scsi_dev_desc[scsi_max_devs].log2blksz = + LOG2(scsi_dev_desc[scsi_max_devs].blksz); scsi_dev_desc[scsi_max_devs].type=perq; init_part(&scsi_dev_desc[scsi_max_devs]); removable: diff --git a/common/usb_storage.c b/common/usb_storage.c index fb322b4..c5db044 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -1430,6 +1430,7 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss, *capacity, *blksz); dev_desc->lba = *capacity; dev_desc->blksz = *blksz; + dev_desc->log2blksz = LOG2(dev_desc->blksz); dev_desc->type = perq; USB_STOR_PRINTF(" address %d\n", dev_desc->target); USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type); diff --git a/drivers/block/ata_piix.c b/drivers/block/ata_piix.c index 1e33a66..fcae448 100644 --- a/drivers/block/ata_piix.c +++ b/drivers/block/ata_piix.c @@ -406,6 +406,7 @@ void sata_identify(int num, int dev) /* assuming HD */ sata_dev_desc[devno].type = DEV_TYPE_HARDDISK; sata_dev_desc[devno].blksz = ATA_BLOCKSIZE; + sata_dev_desc[devno].log2blksz = LOG2(sata_dev_desc[devno].blksz); sata_dev_desc[devno].lun = 0; /* just to fill something in... */ }
diff --git a/drivers/block/pata_bfin.c b/drivers/block/pata_bfin.c index b847dd9..27ecaf4 100644 --- a/drivers/block/pata_bfin.c +++ b/drivers/block/pata_bfin.c @@ -897,6 +897,8 @@ static void bfin_ata_identify(struct ata_port *ap, int dev) /* assuming HD */ sata_dev_desc[ap->port_no].type = DEV_TYPE_HARDDISK; sata_dev_desc[ap->port_no].blksz = ATA_SECT_SIZE; + sata_dev_desc[ap->port_no].log2blksz = + LOG2(sata_dev_desc[ap->port_no].blksz); sata_dev_desc[ap->port_no].lun = 0; /* just to fill something in... */
printf("PATA device#%d %s is found on ata port#%d.\n", diff --git a/drivers/block/systemace.c b/drivers/block/systemace.c index bf29cbb..b08715f 100644 --- a/drivers/block/systemace.c +++ b/drivers/block/systemace.c @@ -127,6 +127,7 @@ block_dev_desc_t *systemace_get_dev(int dev) systemace_dev.part_type = PART_TYPE_UNKNOWN; systemace_dev.type = DEV_TYPE_HARDDISK; systemace_dev.blksz = 512; + systemace_dev.log2blksz = LOG2(systemace_dev.blksz); systemace_dev.removable = 1; systemace_dev.block_read = systemace_read;
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index d732581..c24449a 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1182,6 +1182,7 @@ static int mmc_startup(struct mmc *mmc) mmc->block_dev.lun = 0; mmc->block_dev.type = 0; mmc->block_dev.blksz = mmc->read_bl_len; + mmc->block_dev.log2blksz = LOG2(mmc->block_dev.blksz); mmc->block_dev.lba = lldiv(mmc->capacity, mmc->read_bl_len); sprintf(mmc->block_dev.vendor, "Man %06x Snr %04x%04x", mmc->cid[0] >> 24, (mmc->cid[2] & 0xffff), diff --git a/include/part.h b/include/part.h index 12e9b05..f7c7cc5 100644 --- a/include/part.h +++ b/include/part.h @@ -38,6 +38,7 @@ typedef struct block_dev_desc { #endif lbaint_t lba; /* number of blocks */ unsigned long blksz; /* block size */ + int log2blksz; /* for convenience: log2(blksz) */ char vendor [40+1]; /* IDE model, SCSI Vendor */ char product[20+1]; /* IDE Serial no, SCSI product */ char revision[8+1]; /* firmware revision */ @@ -58,6 +59,10 @@ typedef struct block_dev_desc { #define BLOCK_CNT(size, block_dev_desc) (PAD_COUNT(size, block_dev_desc->blksz)) #define PAD_TO_BLOCKSIZE(size, block_dev_desc) \ (PAD_SIZE(size, block_dev_desc->blksz)) +#define LOG2(x) (((x & 0xaaaaaaaa) ? 1 : 0) + ((x & 0xcccccccc) ? 2 : 0) + \ + ((x & 0xf0f0f0f0) ? 4 : 0) + ((x & 0xff00ff00) ? 8 : 0) + \ + ((x & 0xffff0000) ? 16 : 0)) +#define LOG2_INVALID(type) ((type)((sizeof(type)<<3)-1))
/* Interface types: */ #define IF_TYPE_UNKNOWN 0

On Tue, Apr 09, 2013 at 09:11:56PM -0000, egbert.eich@gmail.com wrote:
From: Egbert Eich eich@suse.com
log2 of the device block size serves as the shift value used to calculate the block number to read in file systems when implementing avaiable block sizes. It is needed quite often in file systems thus it is pre-calculated and stored in the block device descriptor.
Signed-off-by: Egbert Eich eich@suse.com
Applied to u-boot/master, thanks!

From: Egbert Eich eich@suse.com
The 512 byte block size was hard coded in the ext4 file systems. Large harddisks today support bigger block sizes typically 4096 bytes. This patch removes this limitation.
Signed-off-by: Egbert Eich eich@suse.com --- Changes for v2: - Coding style fixes.
fs/ext4/dev.c | 62 ++++++++++++++++++++++++++++++++------------------ fs/ext4/ext4_common.c | 42 ++++++++++++++++++---------------- fs/ext4/ext4_common.h | 2 +- fs/ext4/ext4_journal.c | 6 ++--- fs/ext4/ext4_write.c | 32 ++++++++++++++------------ fs/ext4/ext4fs.c | 14 +++++++----- include/ext4fs.h | 1 + include/ext_common.h | 12 +++------- 8 files changed, 95 insertions(+), 76 deletions(-)
diff --git a/fs/ext4/dev.c b/fs/ext4/dev.c index 464a67d..3e993cc 100644 --- a/fs/ext4/dev.c +++ b/fs/ext4/dev.c @@ -40,6 +40,7 @@ #include <config.h> #include <ext4fs.h> #include <ext_common.h> +#include "ext4_common.h"
unsigned long part_offset;
@@ -48,37 +49,41 @@ static disk_partition_t *part_info;
void ext4fs_set_blk_dev(block_dev_desc_t *rbdd, disk_partition_t *info) { + assert(rbdd->blksz == (1 << rbdd->log2blksz)); ext4fs_block_dev_desc = rbdd; part_info = info; part_offset = info->start; - get_fs()->total_sect = (info->size * info->blksz) / SECTOR_SIZE; + get_fs()->total_sect = (info->size * info->blksz) >> + get_fs()->dev_desc->log2blksz; get_fs()->dev_desc = rbdd; }
int ext4fs_devread(int sector, int byte_offset, int byte_len, char *buf) { - ALLOC_CACHE_ALIGN_BUFFER(char, sec_buf, SECTOR_SIZE); unsigned block_len; + int log2blksz = ext4fs_block_dev_desc->log2blksz; + ALLOC_CACHE_ALIGN_BUFFER(char, sec_buf, (ext4fs_block_dev_desc ? + ext4fs_block_dev_desc->blksz : + 0)); + if (ext4fs_block_dev_desc == NULL) { + printf("** Invalid Block Device Descriptor (NULL)\n"); + return 0; + }
/* Check partition boundaries */ - if ((sector < 0) - || ((sector + ((byte_offset + byte_len - 1) >> SECTOR_BITS)) >= - part_info->size)) { + if ((sector < 0) || + ((sector + ((byte_offset + byte_len - 1) >> log2blksz)) + >= part_info->size)) { printf("%s read outside partition %d\n", __func__, sector); return 0; }
/* Get the read to the beginning of a partition */ - sector += byte_offset >> SECTOR_BITS; - byte_offset &= SECTOR_SIZE - 1; + sector += byte_offset >> log2blksz; + byte_offset &= ext4fs_block_dev_desc->blksz - 1;
debug(" <%d, %d, %d>\n", sector, byte_offset, byte_len);
- if (ext4fs_block_dev_desc == NULL) { - printf("** Invalid Block Device Descriptor (NULL)\n"); - return 0; - } - if (byte_offset != 0) { /* read first part which isn't aligned with start of sector */ if (ext4fs_block_dev_desc-> @@ -89,9 +94,12 @@ int ext4fs_devread(int sector, int byte_offset, int byte_len, char *buf) return 0; } memcpy(buf, sec_buf + byte_offset, - min(SECTOR_SIZE - byte_offset, byte_len)); - buf += min(SECTOR_SIZE - byte_offset, byte_len); - byte_len -= min(SECTOR_SIZE - byte_offset, byte_len); + min(ext4fs_block_dev_desc->blksz + - byte_offset, byte_len)); + buf += min(ext4fs_block_dev_desc->blksz + - byte_offset, byte_len); + byte_len -= min(ext4fs_block_dev_desc->blksz + - byte_offset, byte_len); sector++; }
@@ -99,12 +107,12 @@ int ext4fs_devread(int sector, int byte_offset, int byte_len, char *buf) return 1;
/* read sector aligned part */ - block_len = byte_len & ~(SECTOR_SIZE - 1); + block_len = byte_len & ~(ext4fs_block_dev_desc->blksz - 1);
if (block_len == 0) { - ALLOC_CACHE_ALIGN_BUFFER(u8, p, SECTOR_SIZE); + ALLOC_CACHE_ALIGN_BUFFER(u8, p, ext4fs_block_dev_desc->blksz);
- block_len = SECTOR_SIZE; + block_len = ext4fs_block_dev_desc->blksz; ext4fs_block_dev_desc->block_read(ext4fs_block_dev_desc->dev, part_info->start + sector, 1, (unsigned long *)p); @@ -114,16 +122,16 @@ int ext4fs_devread(int sector, int byte_offset, int byte_len, char *buf)
if (ext4fs_block_dev_desc->block_read(ext4fs_block_dev_desc->dev, part_info->start + sector, - block_len / SECTOR_SIZE, + block_len >> log2blksz, (unsigned long *) buf) != - block_len / SECTOR_SIZE) { + block_len >> log2blksz) { printf(" ** %s read error - block\n", __func__); return 0; } - block_len = byte_len & ~(SECTOR_SIZE - 1); + block_len = byte_len & ~(ext4fs_block_dev_desc->blksz - 1); buf += block_len; byte_len -= block_len; - sector += block_len / SECTOR_SIZE; + sector += block_len / ext4fs_block_dev_desc->blksz;
if (byte_len != 0) { /* read rest of data which are not in whole sector */ @@ -138,3 +146,13 @@ int ext4fs_devread(int sector, int byte_offset, int byte_len, char *buf) } return 1; } + +int ext4_read_superblock(char *buffer) +{ + struct ext_filesystem *fs = get_fs(); + int sect = SUPERBLOCK_START >> fs->dev_desc->log2blksz; + int off = SUPERBLOCK_START % fs->dev_desc->blksz; + + return ext4fs_devread(sect, off, SUPERBLOCK_SIZE, + buffer); +} diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c index f12b805..38c9603 100644 --- a/fs/ext4/ext4_common.c +++ b/fs/ext4/ext4_common.c @@ -71,18 +71,18 @@ void put_ext4(uint64_t off, void *buf, uint32_t size) uint64_t startblock; uint64_t remainder; unsigned char *temp_ptr = NULL; - ALLOC_CACHE_ALIGN_BUFFER(unsigned char, sec_buf, SECTOR_SIZE); struct ext_filesystem *fs = get_fs(); + int log2blksz = fs->dev_desc->log2blks; + ALLOC_CACHE_ALIGN_BUFFER(unsigned char, sec_buf, fs->dev_desc->blksz);
- startblock = off / (uint64_t)SECTOR_SIZE; + startblock = off >> log2blksz; startblock += part_offset; - remainder = off % (uint64_t)SECTOR_SIZE; - remainder &= SECTOR_SIZE - 1; + remainder = off & (uint64_t)(fs->dev_desc->blksz - 1);
if (fs->dev_desc == NULL) return;
- if ((startblock + (size / SECTOR_SIZE)) > + if ((startblock + (size >> log2blksz)) > (part_offset + fs->total_sect)) { printf("part_offset is %lu\n", part_offset); printf("total_sector is %llu\n", fs->total_sect); @@ -101,10 +101,10 @@ void put_ext4(uint64_t off, void *buf, uint32_t size) startblock, 1, sec_buf); } } else { - if (size / SECTOR_SIZE != 0) { + if (size >> log2blksz != 0) { fs->dev_desc->block_write(fs->dev_desc->dev, startblock, - size / SECTOR_SIZE, + size >> log2blksz, (unsigned long *)buf); } else { fs->dev_desc->block_read(fs->dev_desc->dev, @@ -1459,6 +1459,7 @@ static int ext4fs_blockgroup { long int blkno; unsigned int blkoff, desc_per_blk; + int log2blksz = get_fs()->dev_desc->log2blksz;
desc_per_blk = EXT2_BLOCK_SIZE(data) / sizeof(struct ext2_block_group);
@@ -1469,7 +1470,7 @@ static int ext4fs_blockgroup debug("ext4fs read %d group descriptor (blkno %ld blkoff %u)\n", group, blkno, blkoff);
- return ext4fs_devread(blkno << LOG2_EXT2_BLOCK_SIZE(data), + return ext4fs_devread(blkno << (LOG2_BLOCK_SIZE(data) - log2blksz), blkoff, sizeof(struct ext2_block_group), (char *)blkgrp); } @@ -1479,6 +1480,7 @@ int ext4fs_read_inode(struct ext2_data *data, int ino, struct ext2_inode *inode) struct ext2_block_group blkgrp; struct ext2_sblock *sblock = &data->sblock; struct ext_filesystem *fs = get_fs(); + int log2blksz = get_fs()->dev_desc->log2blksz; int inodes_per_block, status; long int blkno; unsigned int blkoff; @@ -1495,7 +1497,8 @@ int ext4fs_read_inode(struct ext2_data *data, int ino, struct ext2_inode *inode) (ino % __le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block; blkoff = (ino % inodes_per_block) * fs->inodesz; /* Read the inode. */ - status = ext4fs_devread(blkno << LOG2_EXT2_BLOCK_SIZE(data), blkoff, + status = ext4fs_devread(blkno << (LOG2_BLOCK_SIZE(data) - log2blksz), + blkoff, sizeof(struct ext2_inode), (char *)inode); if (status == 0) return 0; @@ -1515,7 +1518,9 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) unsigned long long start; /* get the blocksize of the filesystem */ blksz = EXT2_BLOCK_SIZE(ext4fs_root); - log2_blksz = LOG2_EXT2_BLOCK_SIZE(ext4fs_root); + log2_blksz = LOG2_BLOCK_SIZE(ext4fs_root) + - get_fs()->dev_desc->log2blksz; + if (le32_to_cpu(inode->flags) & EXT4_EXTENTS_FL) { char *buf = zalloc(blksz); if (!buf) @@ -1523,11 +1528,11 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) struct ext4_extent_header *ext_block; struct ext4_extent *extent; int i = -1; - ext_block = ext4fs_get_extent_block(ext4fs_root, buf, - (struct ext4_extent_header - *)inode->b. - blocks.dir_blocks, - fileblock, log2_blksz); + ext_block = + ext4fs_get_extent_block(ext4fs_root, buf, + (struct ext4_extent_header *) + inode->b.blocks.dir_blocks, + fileblock, log2_blksz); if (!ext_block) { printf("invalid extent block\n"); free(buf); @@ -1839,7 +1844,7 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) blknr = __le32_to_cpu(ext4fs_indir3_block [rblock % perblock_child]); } - debug("ext4fs_read_block %ld\n", blknr); + debug("read_allocated_block %ld\n", blknr);
return blknr; } @@ -2193,13 +2198,12 @@ int ext4fs_mount(unsigned part_length) struct ext2_data *data; int status; struct ext_filesystem *fs = get_fs(); - data = zalloc(sizeof(struct ext2_data)); + data = zalloc(SUPERBLOCK_SIZE); if (!data) return 0;
/* Read the superblock. */ - status = ext4fs_devread(1 * 2, 0, sizeof(struct ext2_sblock), - (char *)&data->sblock); + status = ext4_read_superblock((char *)&data->sblock);
if (status == 0) goto fail; diff --git a/fs/ext4/ext4_common.h b/fs/ext4/ext4_common.h index 72cd020..6571df6 100644 --- a/fs/ext4/ext4_common.h +++ b/fs/ext4/ext4_common.h @@ -49,7 +49,7 @@
#define S_IFLNK 0120000 /* symbolic link */ #define BLOCK_NO_ONE 1 -#define SUPERBLOCK_SECTOR 2 +#define SUPERBLOCK_START (2 * 512) #define SUPERBLOCK_SIZE 1024 #define F_FILE 1
diff --git a/fs/ext4/ext4_journal.c b/fs/ext4/ext4_journal.c index ba4a7bb..81aa5fc 100644 --- a/fs/ext4/ext4_journal.c +++ b/fs/ext4/ext4_journal.c @@ -534,16 +534,14 @@ end: jsb->s_start = cpu_to_be32(1); jsb->s_sequence = cpu_to_be32(be32_to_cpu(jsb->s_sequence) + 1); /* get the superblock */ - ext4fs_devread(SUPERBLOCK_SECTOR, 0, SUPERBLOCK_SIZE, - (char *)fs->sb); + ext4_read_superblock((char *)fs->sb); fs->sb->feature_incompat |= EXT3_FEATURE_INCOMPAT_RECOVER;
/* Update the super block */ put_ext4((uint64_t) (SUPERBLOCK_SIZE), (struct ext2_sblock *)fs->sb, (uint32_t) SUPERBLOCK_SIZE); - ext4fs_devread(SUPERBLOCK_SECTOR, 0, SUPERBLOCK_SIZE, - (char *)fs->sb); + ext4_read_superblock((char *)fs->sb);
blknr = read_allocated_block(&inode_journal, EXT2_JOURNAL_SUPERBLOCK); diff --git a/fs/ext4/ext4_write.c b/fs/ext4/ext4_write.c index c4e399c..f76a464 100644 --- a/fs/ext4/ext4_write.c +++ b/fs/ext4/ext4_write.c @@ -614,14 +614,13 @@ int ext4fs_init(void) /* populate fs */ fs->blksz = EXT2_BLOCK_SIZE(ext4fs_root); fs->inodesz = INODE_SIZE_FILESYSTEM(ext4fs_root); - fs->sect_perblk = fs->blksz / SECTOR_SIZE; + fs->sect_perblk = fs->blksz >> fs->dev_desc->log2blksz;
/* get the superblock */ fs->sb = zalloc(SUPERBLOCK_SIZE); if (!fs->sb) return -ENOMEM; - if (!ext4fs_devread(SUPERBLOCK_SECTOR, 0, SUPERBLOCK_SIZE, - (char *)fs->sb)) + if (!ext4_read_superblock((char *)fs->sb)) goto fail;
/* init journal */ @@ -722,7 +721,7 @@ void ext4fs_deinit(void) ext4fs_free_journal();
/* get the superblock */ - ext4fs_devread(SUPERBLOCK_SECTOR, 0, SUPERBLOCK_SIZE, (char *)fs->sb); + ext4_read_superblock((char *)fs->sb); fs->sb->feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER; put_ext4((uint64_t)(SUPERBLOCK_SIZE), (struct ext2_sblock *)fs->sb, (uint32_t)SUPERBLOCK_SIZE); @@ -766,7 +765,8 @@ static int ext4fs_write_file(struct ext2_inode *file_inode, { int i; int blockcnt; - int log2blocksize = LOG2_EXT2_BLOCK_SIZE(ext4fs_root); + int log2blksz = fs->dev_desc->log2blksz; + int log2_fs_blocksize = LOG2_BLOCK_SIZE(ext4fs_root) - log2blksz; unsigned int filesize = __le32_to_cpu(file_inode->size); struct ext_filesystem *fs = get_fs(); int previous_block_number = -1; @@ -789,16 +789,16 @@ static int ext4fs_write_file(struct ext2_inode *file_inode, if (blknr < 0) return -1;
- blknr = blknr << log2blocksize; + blknr = blknr << log2_fs_blocksize;
if (blknr) { if (previous_block_number != -1) { if (delayed_next == blknr) { delayed_extent += blockend; - delayed_next += blockend >> SECTOR_BITS; + delayed_next += blockend >> log2blksz; } else { /* spill */ - put_ext4((uint64_t) (delayed_start * - SECTOR_SIZE), + put_ext4((uint64_t) + (delayed_start << log2blksz), delayed_buf, (uint32_t) delayed_extent); previous_block_number = blknr; @@ -806,7 +806,7 @@ static int ext4fs_write_file(struct ext2_inode *file_inode, delayed_extent = blockend; delayed_buf = buf; delayed_next = blknr + - (blockend >> SECTOR_BITS); + (blockend >> log2blksz); } } else { previous_block_number = blknr; @@ -814,13 +814,14 @@ static int ext4fs_write_file(struct ext2_inode *file_inode, delayed_extent = blockend; delayed_buf = buf; delayed_next = blknr + - (blockend >> SECTOR_BITS); + (blockend >> log2blksz); } } else { if (previous_block_number != -1) { /* spill */ - put_ext4((uint64_t) (delayed_start * - SECTOR_SIZE), delayed_buf, + put_ext4((uint64_t) (delayed_start << + log2blksz), + delayed_buf, (uint32_t) delayed_extent); previous_block_number = -1; } @@ -830,7 +831,7 @@ static int ext4fs_write_file(struct ext2_inode *file_inode, } if (previous_block_number != -1) { /* spill */ - put_ext4((uint64_t) (delayed_start * SECTOR_SIZE), + put_ext4((uint64_t) (delayed_start << log2blksz), delayed_buf, (uint32_t) delayed_extent); previous_block_number = -1; } @@ -921,7 +922,8 @@ int ext4fs_write(const char *fname, unsigned char *buffer, /* Allocate data blocks */ ext4fs_allocate_blocks(file_inode, blocks_remaining, &blks_reqd_for_file); - file_inode->blockcnt = (blks_reqd_for_file * fs->blksz) / SECTOR_SIZE; + file_inode->blockcnt = (blks_reqd_for_file * fs->blksz) >> + fs->dev_desc->log2blksz;
temp_ptr = zalloc(fs->blksz); if (!temp_ptr) diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c index 4dddde2..1954afb 100644 --- a/fs/ext4/ext4fs.c +++ b/fs/ext4/ext4fs.c @@ -60,10 +60,12 @@ void ext4fs_free_node(struct ext2fs_node *node, struct ext2fs_node *currroot) int ext4fs_read_file(struct ext2fs_node *node, int pos, unsigned int len, char *buf) { + struct ext_filesystem *fs = get_fs(); int i; int blockcnt; - int log2blocksize = LOG2_EXT2_BLOCK_SIZE(node->data); - int blocksize = 1 << (log2blocksize + DISK_SECTOR_BITS); + int log2blksz = fs->dev_desc->log2blksz; + int log2_fs_blocksize = LOG2_BLOCK_SIZE(node->data) - log2blksz; + int blocksize = (1 << (log2_fs_blocksize + log2blksz)); unsigned int filesize = __le32_to_cpu(node->inode.size); int previous_block_number = -1; int delayed_start = 0; @@ -88,7 +90,7 @@ int ext4fs_read_file(struct ext2fs_node *node, int pos, if (blknr < 0) return -1;
- blknr = blknr << log2blocksize; + blknr = blknr << log2_fs_blocksize;
/* Last block. */ if (i == blockcnt - 1) { @@ -110,7 +112,7 @@ int ext4fs_read_file(struct ext2fs_node *node, int pos, if (previous_block_number != -1) { if (delayed_next == blknr) { delayed_extent += blockend; - delayed_next += blockend >> SECTOR_BITS; + delayed_next += blockend >> log2blksz; } else { /* spill */ status = ext4fs_devread(delayed_start, delayed_skipfirst, @@ -124,7 +126,7 @@ int ext4fs_read_file(struct ext2fs_node *node, int pos, delayed_skipfirst = skipfirst; delayed_buf = buf; delayed_next = blknr + - (blockend >> SECTOR_BITS); + (blockend >> log2blksz); } } else { previous_block_number = blknr; @@ -133,7 +135,7 @@ int ext4fs_read_file(struct ext2fs_node *node, int pos, delayed_skipfirst = skipfirst; delayed_buf = buf; delayed_next = blknr + - (blockend >> SECTOR_BITS); + (blockend >> log2blksz); } } else { if (previous_block_number != -1) { diff --git a/include/ext4fs.h b/include/ext4fs.h index 025a2e8..379f7eb 100644 --- a/include/ext4fs.h +++ b/include/ext4fs.h @@ -141,4 +141,5 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock); int ext4fs_probe(block_dev_desc_t *fs_dev_desc, disk_partition_t *fs_partition); int ext4_read_file(const char *filename, void *buf, int offset, int len); +int ext4_read_superblock(char *buffer); #endif diff --git a/include/ext_common.h b/include/ext_common.h index 86373a6..78a7808 100644 --- a/include/ext_common.h +++ b/include/ext_common.h @@ -34,7 +34,6 @@ #define __EXT_COMMON__ #include <command.h> #define SECTOR_SIZE 0x200 -#define SECTOR_BITS 9
/* Magic value used to identify an ext2 filesystem. */ #define EXT2_MAGIC 0xEF53 @@ -58,18 +57,13 @@ #define FILETYPE_INO_SYMLINK 0120000 #define EXT2_ROOT_INO 2 /* Root inode */
-/* Bits used as offset in sector */ -#define DISK_SECTOR_BITS 9 /* The size of an ext2 block in bytes. */ #define EXT2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE(data))
-/* Log2 size of ext2 block in 512 blocks. */ -#define LOG2_EXT2_BLOCK_SIZE(data) (__le32_to_cpu \ - (data->sblock.log2_block_size) + 1) - /* Log2 size of ext2 block in bytes. */ -#define LOG2_BLOCK_SIZE(data) (__le32_to_cpu \ - (data->sblock.log2_block_size) + 10) +#define LOG2_BLOCK_SIZE(data) (__le32_to_cpu \ + (data->sblock.log2_block_size) \ + + EXT2_MIN_BLOCK_LOG_SIZE) #define INODE_SIZE_FILESYSTEM(data) (__le32_to_cpu \ (data->sblock.inode_size))
participants (2)
-
Egbert Eich
-
Tom Rini