[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