[U-Boot-Users] PATCH: Update U-Boot EXT2 Filesystem to support dynamic inode size and optimize ext2 read function to fasten read speed!
Ryan CHEN
ryan.chen at st.com
Tue Jul 29 10:48:51 CEST 2008
Description:
The patch updates /fs/ext2/ext2fs.c file. There are two aims:
1. Make U-Boot could support the EXT2 dynamic version that ext2_inode_size beyond 128bytes.
One new feature be involved: CFG_EXT2_SUPPORT_DYNAMIC_REV
Refer to: linux-2.6.24.3 source code.
2. Make EXT2 read more fast.
One new feature be involved: CFG_OPTIMIZE_EXT2_READ
commit f4120b0f4f06cd1a382bb562d7fe33ea554a1982
Parent: 699f05125509249072a0b865c8d35520d97cd501
Author: Ryan Chen <ryan.chen at st.com>
Date: Tue Jul 29 11:57:11 2008 -0400
Signed-off-by: Ryan Chen <ryan.chen at st.com>
modified: fs/ext2/ext2fs.c
diff --git a/fs/ext2/ext2fs.c b/fs/ext2/ext2fs.c
old mode 100644
new mode 100755
index 7833551..3946978
--- a/fs/ext2/ext2fs.c
+++ b/fs/ext2/ext2fs.c
@@ -29,6 +29,7 @@
#include <ext2fs.h>
#include <malloc.h>
#include <asm/byteorder.h>
+#define CFG_EXT2_SUPPORT_DYNAMIC_REV
extern int ext2fs_devread (int sector, int byte_offset, int byte_len,
char *buf);
@@ -66,6 +67,17 @@ extern int ext2fs_devread (int sector, int byte_offset, int byte_len,
/* The size of an ext2 block in bytes. */
#define EXT2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE(data))
+#ifdef CFG_EXT2_SUPPORT_DYNAMIC_REV
+/*
+ * Revision levels
+ */
+#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
+#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
+
+#define EXT2_GOOD_OLD_INODE_SIZE 128
+uint32_t ext2_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
+#endif
+
/* The ext2 superblock. */
struct ext2_sblock {
uint32_t total_inodes;
@@ -217,7 +229,11 @@ static int ext2fs_read_inode
if (status == 0) {
return (0);
}
+#ifdef CFG_EXT2_SUPPORT_DYNAMIC_REV
+ inodes_per_block = EXT2_BLOCK_SIZE (data) / ext2_inode_size;
+#else
inodes_per_block = EXT2_BLOCK_SIZE (data) / 128;
+#endif
blkno = (ino % __le32_to_cpu (sblock->inodes_per_group)) /
inodes_per_block;
blkoff = (ino % __le32_to_cpu (sblock->inodes_per_group)) %
@@ -226,10 +242,17 @@ static int ext2fs_read_inode
printf ("ext2fs read inode blkno %d blkoff %d\n", blkno, blkoff);
#endif
/* Read the inode. */
+#ifdef CFG_EXT2_SUPPORT_DYNAMIC_REV
+ status = ext2fs_devread (((__le32_to_cpu (blkgrp.inode_table_id) +
+ blkno) << LOG2_EXT2_BLOCK_SIZE (data)),
+ ext2_inode_size * blkoff,
+ sizeof (struct ext2_inode), (char *) inode);
+#else
status = ext2fs_devread (((__le32_to_cpu (blkgrp.inode_table_id) +
blkno) << LOG2_EXT2_BLOCK_SIZE (data)),
sizeof (struct ext2_inode) * blkoff,
sizeof (struct ext2_inode), (char *) inode);
+#endif
if (status == 0) {
return (0);
}
@@ -243,8 +266,13 @@ void ext2fs_free_node (ext2fs_node_t node, ext2fs_node_t currroot) {
}
}
+#define CFG_OPTIMIZE_EXT2_READ
+#ifdef CFG_OPTIMIZE_EXT2_READ
+static int ext2fs_read_block (ext2fs_node_t node, int fileblock, int *stream) {
+#else
static int ext2fs_read_block (ext2fs_node_t node, int fileblock) {
+#endif
struct ext2_data *data = node->data;
struct ext2_inode *inode = &node->inode;
int blknr;
@@ -252,9 +280,20 @@ static int ext2fs_read_block (ext2fs_node_t node, int fileblock) {
int log2_blksz = LOG2_EXT2_BLOCK_SIZE (data);
int status;
+#ifdef CFG_OPTIMIZE_EXT2_READ
+ *stream = 1;/* itself */
+#endif
+
/* Direct blocks. */
if (fileblock < INDIRECT_BLOCKS) {
blknr = __le32_to_cpu (inode->b.blocks.dir_blocks[fileblock]);
+#ifdef CFG_OPTIMIZE_EXT2_READ
+ while(((inode->b.blocks.dir_blocks[fileblock + 1] -
+ inode->b.blocks.dir_blocks[fileblock]) == 1) && (fileblock < INDIRECT_BLOCKS - 1)) {
+ fileblock++;
+ *stream += 1;
+ }
+#endif
}
/* Indirect. */
else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4))) {
@@ -294,6 +333,13 @@ static int ext2fs_read_block (ext2fs_node_t node, int fileblock) {
}
blknr = __le32_to_cpu (indir1_block
[fileblock - INDIRECT_BLOCKS]);
+#ifdef CFG_OPTIMIZE_EXT2_READ
+ while(((__le32_to_cpu (indir1_block[fileblock - INDIRECT_BLOCKS + 1]) - \
+ __le32_to_cpu (indir1_block[fileblock - INDIRECT_BLOCKS])) == 1) && (fileblock < (blksz - 1))) {
+ fileblock++;
+ *stream += 1;
+ }
+#endif
}
/* Double indirect. */
else if (fileblock <
@@ -301,6 +347,9 @@ static int ext2fs_read_block (ext2fs_node_t node, int fileblock) {
unsigned int perblock = blksz / 4;
unsigned int rblock = fileblock - (INDIRECT_BLOCKS
+ blksz / 4);
+#ifdef CFG_OPTIMIZE_EXT2_READ
+ int rbcnt = 0;
+#endif
if (indir1_block == NULL) {
indir1_block = (uint32_t *) malloc (blksz);
@@ -370,6 +419,14 @@ static int ext2fs_read_block (ext2fs_node_t node, int fileblock) {
__le32_to_cpu (indir1_block[rblock / perblock]) << log2_blksz;
}
blknr = __le32_to_cpu (indir2_block[rblock % perblock]);
+#ifdef CFG_OPTIMIZE_EXT2_READ
+ rbcnt = rblock % perblock;
+ while(((__le32_to_cpu (indir2_block[rbcnt + 1]) - \
+ __le32_to_cpu (indir2_block[rbcnt])) == 1) && (rbcnt < (blksz - 1))) {
+ rbcnt++;
+ *stream += 1;
+ }
+#endif
}
/* Tripple indirect. */
else {
@@ -382,7 +439,57 @@ static int ext2fs_read_block (ext2fs_node_t node, int fileblock) {
return (blknr);
}
+#ifdef CFG_OPTIMIZE_EXT2_READ
+int ext2fs_read_file
+ (ext2fs_node_t node, int pos, unsigned int len, char *buf) {
+ int log2blocksize = LOG2_EXT2_BLOCK_SIZE (node->data);
+ int blocksize = 1 << (log2blocksize + DISK_SECTOR_BITS);
+ unsigned int filesize = __le32_to_cpu(node->inode.size);
+ int blknr;
+ int blockend;
+ int status;
+ int remain = len;
+ char *buffer = buf;
+ int stream = 0;
+ int cur = pos / blocksize;
+ int blockoff = pos % blocksize;
+
+ /* Adjust len so it we can't read past the end of the file. */
+ if (len > filesize) {
+ len = filesize;
+ }
+ while (remain > 0) {
+ blknr = ext2fs_read_block (node, cur, &stream);
+ if (blknr < 0) {
+ return (-1);
+ }
+ blknr = blknr << log2blocksize;
+
+ if(remain < blocksize * stream) {
+ blockend = remain;
+ } else {
+ blockend = blocksize * stream;
+ }
+
+ status = ext2fs_devread (blknr, blockoff, blockend, buffer);
+ if (status == 0) {
+ return (-1);
+ }
+
+ remain -= blockend;
+ buffer += blockend;
+ cur += stream;
+ blockoff = 0;
+
+ if(remain == 0)
+ return (len);
+ else if(remain < 0)
+ return (-1);
+ }
+ return (len);
+}
+#else
int ext2fs_read_file
(ext2fs_node_t node, int pos, unsigned int len, char *buf) {
int i;
@@ -390,7 +497,7 @@ int ext2fs_read_file
int log2blocksize = LOG2_EXT2_BLOCK_SIZE (node->data);
int blocksize = 1 << (log2blocksize + DISK_SECTOR_BITS);
unsigned int filesize = __le32_to_cpu(node->inode.size);
-
+
/* Adjust len so it we can't read past the end of the file. */
if (len > filesize) {
len = filesize;
@@ -409,7 +516,7 @@ int ext2fs_read_file
return (-1);
}
blknr = blknr << log2blocksize;
-
+
/* Last block. */
if (i == blockcnt - 1) {
blockend = (len + pos) % blocksize;
@@ -442,6 +549,7 @@ int ext2fs_read_file
}
return (len);
}
+#endif
static int ext2fs_iterate_dir (ext2fs_node_t dir, char *name, ext2fs_node_t * fnode, int *ftype)
@@ -854,6 +962,17 @@ int ext2fs_mount (unsigned part_length) {
if (__le16_to_cpu (data->sblock.magic) != EXT2_MAGIC) {
goto fail;
}
+#ifdef CFG_EXT2_SUPPORT_DYNAMIC_REV
+#ifdef DEBUG
+ printf("revision_level = 0x%x, inode_size = 0x%x\n", data->sblock.revision_level, data->sblock.inode_size);
+#endif
+ if (__le32_to_cpu (data->sblock.revision_level) == EXT2_GOOD_OLD_REV) {
+ ext2_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
+ } else {
+ ext2_inode_size = __le16_to_cpu (data->sblock.inode_size);
+ }
+#endif
+
data->diropen.data = data;
data->diropen.ino = 2;
data->diropen.inode_read = 1;
Best Regards,
Ryan Chen
More information about the U-Boot
mailing list