uboot ext4load is very slow to read the kernel image into memory

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

uboot ext4load is very slow to read the kernel image into memory

Jump to solution
8,092 Views
qiweiwen
Contributor I

We have a custom ARM board based on the imx6 quad processor and have been using modified Boundary Devices Android release, including their uboot 2015.07.

We found a strange problem with the boot process: late in the boot script, uboot tries to pull the Linux kernel image from mmc 1:1 to physical memory 10800000. The kernel is 8MB large and this process takes ~27 seconds, at ~300KB/s. I tried reading only the first 1.6MB of the kernel image, and the speed is the same. Compare that with the time to load Android's initial ramdisk:

=> load mmc 1:1 13800000 zImage 186A00 0
1600000 bytes read in 5108 ms (305.7 KiB/s)
=> load mmc 1:1 13800000 uramdisk.img 
1643223 bytes read in 91 ms (17.2 MiB/s)

 

In desparation, I got rid of everything in the boot partition save for zImage, and even ran e4defrag on it to reduce the number of extents from 13 to 5, and the result is exactly the same:

=> ext4load mmc 1:1 13800000 zImage
8615840 bytes read in 27166 ms (309.6 KiB/s)

What might be the cause of the problem?

(I haven't yet tried upgrading uboot to Boundary Devices' latest, but I hesitate to do it because it entails migrating all of our modifications to a new code base)

1 Solution
5,523 Views
qiweiwen
Contributor I

Found the cause of the problem. uboot's ext4fs_read_file function will call read_allocated_block function for each logical block in the file to map it to a physical device offset by walking the extent tree. However, the whole point about extents is that they are contiguous both in the file and on the disk, so once an extent block is fetched, it doesn't need to be fetched again. Only files with fewer than 5 extents, in which case all metadata is found in the inode, has acceptable performance.


The workaround is to add caching to read_allocated_block so that once the first "cache miss" causes the extent block to be read from disk, it's kept around for all logical offsets covered by that extent.

View solution in original post

0 Kudos
5 Replies
5,523 Views
mb1
Contributor III

I ran into a similar problem when loading the Kernel from MMC on i.MX8MM. My solution was to change /boot partitions format to FAT. So if ext4 is not indispensable for you, this might help you for now. 

0 Kudos
5,523 Views
sp_qoriq
Contributor III

qiweiwen Did you find a patch that addresses this issue? If so, can you please point me to it? Thanks.

0 Kudos
4,915 Views
scott3303
Contributor II
5,523 Views
romainizard
Contributor I

There is a commit from 2014 in the U-Boot repository that added the support for ext4 extent caching.

"fc0fc50f38 ext4fs: Add ext4 extent cache for read operations"

But as it broke the ext4 write support, it was quickly reverted.

0 Kudos
5,524 Views
qiweiwen
Contributor I

Found the cause of the problem. uboot's ext4fs_read_file function will call read_allocated_block function for each logical block in the file to map it to a physical device offset by walking the extent tree. However, the whole point about extents is that they are contiguous both in the file and on the disk, so once an extent block is fetched, it doesn't need to be fetched again. Only files with fewer than 5 extents, in which case all metadata is found in the inode, has acceptable performance.


The workaround is to add caching to read_allocated_block so that once the first "cache miss" causes the extent block to be read from disk, it's kept around for all logical offsets covered by that extent.

0 Kudos