Skip to content
Snippets Groups Projects
Select Git revision
  • a7e8c15f71456d55ccb27f843862af03a00e0957
  • master default protected
  • early-display
  • variant-emmc-nvme-boot
  • 2023-01-25
  • v3
  • variant-emmc-nvme-boot
  • 2020-06-01
8 results

ext4_common.c

Blame
  • Forked from Reform / reform-boundary-uboot
    Source project has a limited visibility.
    • Ionut Nicu's avatar
      fc0fc50f
      ext4fs: Add ext4 extent cache for read operations · fc0fc50f
      Ionut Nicu authored
      
      In an ext4 filesystem, the inode corresponding to a file has a 60-byte
      area which contains an extent header structure and up to 4 extent
      structures (5 x 12 bytes).
      
      For files that need more than 4 extents to be represented (either files
      larger than 4 x 128MB = 512MB or smaller files but very fragmented),
      ext4 creates extent index structures. Each extent index points to a 4KB
      physical block where one extent header and additional 340 extents could
      be stored.
      
      The current u-boot ext4 code is very inefficient when it tries to load a
      file which has extent indexes. For each logical file block the code will
      read over and over again the same blocks of 4096 bytes from the disk.
      
      Since the extent tree in a file is always the same, we can cache the
      extent structures in memory before actually starting to read the file.
      
      This patch creates a simple linked list of structures holding information
      about all the extents used to represent a file. The list is sorted by
      the logical block number (ee_block) so that we can easily find the
      proper extent information for any file block.
      
      Without this patch, a 69MB file which had just one extent index pointing
      to a block with another 6 extents was read in approximately 3 minutes.
      With this patch applied the same file can be read in almost 20 seconds.
      
      Signed-off-by: default avatarIonut Nicu <ioan.nicu.ext@nsn.com>
      fc0fc50f
      History
      ext4fs: Add ext4 extent cache for read operations
      Ionut Nicu authored
      
      In an ext4 filesystem, the inode corresponding to a file has a 60-byte
      area which contains an extent header structure and up to 4 extent
      structures (5 x 12 bytes).
      
      For files that need more than 4 extents to be represented (either files
      larger than 4 x 128MB = 512MB or smaller files but very fragmented),
      ext4 creates extent index structures. Each extent index points to a 4KB
      physical block where one extent header and additional 340 extents could
      be stored.
      
      The current u-boot ext4 code is very inefficient when it tries to load a
      file which has extent indexes. For each logical file block the code will
      read over and over again the same blocks of 4096 bytes from the disk.
      
      Since the extent tree in a file is always the same, we can cache the
      extent structures in memory before actually starting to read the file.
      
      This patch creates a simple linked list of structures holding information
      about all the extents used to represent a file. The list is sorted by
      the logical block number (ee_block) so that we can easily find the
      proper extent information for any file block.
      
      Without this patch, a 69MB file which had just one extent index pointing
      to a block with another 6 extents was read in approximately 3 minutes.
      With this patch applied the same file can be read in almost 20 seconds.
      
      Signed-off-by: default avatarIonut Nicu <ioan.nicu.ext@nsn.com>
    spl_nand.c 3.51 KiB
    /*
     * Copyright (C) 2011
     * Corscience GmbH & Co. KG - Simon Schwarz <schwarz@corscience.de>
     *
     * SPDX-License-Identifier:	GPL-2.0+
     */
    #include <common.h>
    #include <config.h>
    #include <spl.h>
    #include <asm/io.h>
    #include <nand.h>
    #include <libfdt_env.h>
    #include <fdt.h>
    
    #if defined(CONFIG_SPL_NAND_RAW_ONLY)
    int spl_nand_load_image(void)
    {
    	nand_init();
    
    	nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
    			    CONFIG_SYS_NAND_U_BOOT_SIZE,
    			    (void *)CONFIG_SYS_NAND_U_BOOT_DST);
    	spl_set_header_raw_uboot(&spl_image);
    	nand_deselect();
    
    	return 0;
    }
    #else
    
    static ulong spl_nand_fit_read(struct spl_load_info *load, ulong offs,
    			       ulong size, void *dst)
    {
    	int ret;
    
    	ret = nand_spl_load_image(offs, size, dst);
    	if (!ret)
    		return size;
    	else
    		return 0;
    }
    
    static int spl_nand_load_element(int offset, struct image_header *header)
    {
    	int err;
    
    	err = nand_spl_load_image(offset, sizeof(*header), (void *)header);
    	if (err)
    		return err;
    
    	if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
    	    image_get_magic(header) == FDT_MAGIC) {
    		struct spl_load_info load;
    
    		debug("Found FIT\n");
    		load.dev = NULL;
    		load.priv = NULL;
    		load.filename = NULL;
    		load.bl_len = 1;
    		load.read = spl_nand_fit_read;
    		return spl_load_simple_fit(&load, offset, header);
    	} else {
    		err = spl_parse_image_header(&spl_image, header);
    		if (err)
    			return err;
    		return nand_spl_load_image(offset, spl_image.size,
    					   (void *)(ulong)spl_image.load_addr);
    	}
    }
    
    int spl_nand_load_image(void)
    {
    	int err;
    	struct image_header *header;
    	int *src __attribute__((unused));
    	int *dst __attribute__((unused));
    
    #ifdef CONFIG_SPL_NAND_SOFTECC
    	debug("spl: nand - using sw ecc\n");
    #else
    	debug("spl: nand - using hw ecc\n");
    #endif
    	nand_init();
    
    	/*use CONFIG_SYS_TEXT_BASE as temporary storage area */
    	header = (struct image_header *)(CONFIG_SYS_TEXT_BASE);
    #ifdef CONFIG_SPL_OS_BOOT
    	if (!spl_start_uboot()) {
    		/*
    		 * load parameter image
    		 * load to temp position since nand_spl_load_image reads
    		 * a whole block which is typically larger than
    		 * CONFIG_CMD_SPL_WRITE_SIZE therefore may overwrite
    		 * following sections like BSS
    		 */
    		nand_spl_load_image(CONFIG_CMD_SPL_NAND_OFS,
    			CONFIG_CMD_SPL_WRITE_SIZE,
    			(void *)CONFIG_SYS_TEXT_BASE);
    		/* copy to destintion */
    		for (dst = (int *)CONFIG_SYS_SPL_ARGS_ADDR,
    				src = (int *)CONFIG_SYS_TEXT_BASE;
    				src < (int *)(CONFIG_SYS_TEXT_BASE +
    				CONFIG_CMD_SPL_WRITE_SIZE);
    				src++, dst++) {
    			writel(readl(src), dst);
    		}
    
    		/* load linux */
    		nand_spl_load_image(CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
    			sizeof(*header), (void *)header);
    		err = spl_parse_image_header(&spl_image, header);
    		if (err)
    			return err;
    		if (header->ih_os == IH_OS_LINUX) {
    			/* happy - was a linux */
    			err = nand_spl_load_image(
    				CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
    				spl_image.size,
    				(void *)spl_image.load_addr);
    			nand_deselect();
    			return err;
    		} else {
    			puts("The Expected Linux image was not "
    				"found. Please check your NAND "
    				"configuration.\n");
    			puts("Trying to start u-boot now...\n");
    		}
    	}
    #endif
    #ifdef CONFIG_NAND_ENV_DST
    	spl_nand_load_element(CONFIG_ENV_OFFSET, header);
    #ifdef CONFIG_ENV_OFFSET_REDUND
    	spl_nand_load_element(CONFIG_ENV_OFFSET_REDUND, header);
    #endif
    #endif
    	/* Load u-boot */
    	err = spl_nand_load_element(CONFIG_SYS_NAND_U_BOOT_OFFS, header);
    #ifdef CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND
    #if CONFIG_SYS_NAND_U_BOOT_OFFS != CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND
    	if (err)
    		err = spl_nand_load_element(CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND,
    					    header);
    #endif
    #endif
    	nand_deselect();
    	return err;
    }
    #endif