From: Tom Rini Date: Wed, 26 Feb 2014 13:18:58 +0000 (-0500) Subject: Revert "ext4fs: Add ext4 extent cache for read operations" X-Git-Tag: v2014.04-rc2~73 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=715b56fe2b47e073e6f2425e0cedba0e92a4014d;p=oweals%2Fu-boot.git Revert "ext4fs: Add ext4 extent cache for read operations" This reverts commit fc0fc50f38a4d7d0554558076a79dfe8b0d78cd5. The author has asked on the mailing list that we revert this for now as it breaks write support. Reported-by: Ɓukasz Majewski Signed-off-by: Tom Rini --- diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c index 6584892dd2..02da75c084 100644 --- a/fs/ext4/ext4_common.c +++ b/fs/ext4/ext4_common.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include "ext4_common.h" @@ -45,14 +44,6 @@ int ext4fs_indir3_blkno = -1; struct ext2_inode *g_parent_inode; static int symlinknest; -struct ext4_extent_node { - uint32_t block; - uint16_t len; - uint64_t start; - struct list_head lh; -}; -static LIST_HEAD(ext4_extent_lh); - #if defined(CONFIG_EXT4_WRITE) uint32_t ext4fs_div_roundup(uint32_t size, uint32_t n) { @@ -1416,102 +1407,45 @@ void ext4fs_allocate_blocks(struct ext2_inode *file_inode, #endif -static void ext4fs_extent_cache_insert(struct ext4_extent_node *new) -{ - struct ext4_extent_node *node; - - list_for_each_entry(node, &ext4_extent_lh, lh) - if (node->block > new->block) { - list_add_tail(&new->lh, &node->lh); - return; - } - list_add_tail(&new->lh, &ext4_extent_lh); -} - -static int __ext4fs_build_extent_cache(struct ext2_data *data, - struct ext4_extent_header *ext_block) +static struct ext4_extent_header *ext4fs_get_extent_block + (struct ext2_data *data, char *buf, + struct ext4_extent_header *ext_block, + uint32_t fileblock, int log2_blksz) { - int blksz = EXT2_BLOCK_SIZE(data); - int log2_blksz = LOG2_BLOCK_SIZE(data) - - get_fs()->dev_desc->log2blksz; - struct ext4_extent_node *node; struct ext4_extent_idx *index; - struct ext4_extent *extent; unsigned long long block; - char *buf; - int i, err; + int blksz = EXT2_BLOCK_SIZE(data); + int i; - if (le16_to_cpu(ext_block->eh_magic) != EXT4_EXT_MAGIC) - return -EINVAL; + while (1) { + index = (struct ext4_extent_idx *)(ext_block + 1); - if (ext_block->eh_depth == 0) { - extent = (struct ext4_extent *)(ext_block + 1); - for (i = 0; i < le16_to_cpu(ext_block->eh_entries); i++) { - node = malloc(sizeof(*node)); - if (!node) - return -ENOMEM; - node->block = le32_to_cpu(extent[i].ee_block); - node->len = le16_to_cpu(extent[i].ee_len); - node->start = le16_to_cpu(extent[i].ee_start_hi); - node->start = (node->start << 32) + - le32_to_cpu(extent[i].ee_start_lo); - ext4fs_extent_cache_insert(node); - } - return 0; - } + if (le16_to_cpu(ext_block->eh_magic) != EXT4_EXT_MAGIC) + return 0; - index = (struct ext4_extent_idx *)(ext_block + 1); - for (i = 0; i < le16_to_cpu(ext_block->eh_entries); i++) { - buf = malloc(blksz); - if (!buf) - return -ENOMEM; + if (ext_block->eh_depth == 0) + return ext_block; + i = -1; + do { + i++; + if (i >= le16_to_cpu(ext_block->eh_entries)) + break; + } while (fileblock >= le32_to_cpu(index[i].ei_block)); + + if (--i < 0) + return 0; block = le16_to_cpu(index[i].ei_leaf_hi); block = (block << 32) + le32_to_cpu(index[i].ei_leaf_lo); - if (!ext4fs_devread(block << log2_blksz, 0, blksz, buf)) { - free(buf); - return -EIO; - } - - err = __ext4fs_build_extent_cache(data, - (struct ext4_extent_header *) buf); - free(buf); - if (err < 0) - return err; - } - - return 0; -} - -int ext4fs_build_extent_cache(struct ext2_inode *inode) -{ - return __ext4fs_build_extent_cache(ext4fs_root, - (struct ext4_extent_header *) - inode->b.blocks.dir_blocks); -} - -void ext4fs_free_extent_cache(void) -{ - struct ext4_extent_node *node, *tmp; - - list_for_each_entry_safe(node, tmp, &ext4_extent_lh, lh) { - list_del(&node->lh); - free(node); + if (ext4fs_devread((lbaint_t)block << log2_blksz, 0, blksz, + buf)) + ext_block = (struct ext4_extent_header *)buf; + else + return 0; } } -static struct ext4_extent_node *ext4fs_extent_cache_get(uint32_t block) -{ - struct ext4_extent_node *node; - - list_for_each_entry(node, &ext4_extent_lh, lh) - if (block >= node->block && block < node->block + node->len) - return node; - - return NULL; -} - static int ext4fs_blockgroup (struct ext2_data *data, int group, struct ext2_block_group *blkgrp) { @@ -1574,22 +1508,54 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock) long int rblock; long int perblock_parent; long int perblock_child; - + unsigned long long start; /* get the blocksize of the filesystem */ blksz = 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) { - struct ext4_extent_node *node; + char *buf = zalloc(blksz); + if (!buf) + return -ENOMEM; + 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); + if (!ext_block) { + printf("invalid extent block\n"); + free(buf); + return -EINVAL; + } - node = ext4fs_extent_cache_get(fileblock); - if (!node) { - printf("Extent Error\n"); - return -1; + extent = (struct ext4_extent *)(ext_block + 1); + + do { + i++; + if (i >= le16_to_cpu(ext_block->eh_entries)) + break; + } while (fileblock >= le32_to_cpu(extent[i].ee_block)); + if (--i >= 0) { + fileblock -= le32_to_cpu(extent[i].ee_block); + if (fileblock >= le16_to_cpu(extent[i].ee_len)) { + free(buf); + return 0; + } + + start = le16_to_cpu(extent[i].ee_start_hi); + start = (start << 32) + + le32_to_cpu(extent[i].ee_start_lo); + free(buf); + return fileblock + start; } - return fileblock - node->block + node->start; + printf("Extent Error\n"); + free(buf); + return -1; } /* Direct blocks. */ diff --git a/fs/ext4/ext4_common.h b/fs/ext4/ext4_common.h index a9fd8c6573..5fa1719f2e 100644 --- a/fs/ext4/ext4_common.h +++ b/fs/ext4/ext4_common.h @@ -57,9 +57,6 @@ int ext4fs_find_file(const char *path, struct ext2fs_node *rootnode, int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name, struct ext2fs_node **fnode, int *ftype); -int ext4fs_build_extent_cache(struct ext2_inode *inode); -void ext4fs_free_extent_cache(void); - #if defined(CONFIG_EXT4_WRITE) uint32_t ext4fs_div_roundup(uint32_t size, uint32_t n); int ext4fs_checksum_update(unsigned int i); diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c index 4f1b4c8bce..417ce7b63b 100644 --- a/fs/ext4/ext4fs.c +++ b/fs/ext4/ext4fs.c @@ -63,14 +63,6 @@ int ext4fs_read_file(struct ext2fs_node *node, int pos, char *delayed_buf = NULL; short status; - if (le32_to_cpu(node->inode.flags) & EXT4_EXTENTS_FL) { - if (ext4fs_build_extent_cache(&node->inode)) { - printf("Error building extent cache!\n"); - len = -1; - goto out_exit; - } - } - /* Adjust len so it we can't read past the end of the file. */ if (len > filesize) len = filesize; @@ -83,10 +75,8 @@ int ext4fs_read_file(struct ext2fs_node *node, int pos, int blockend = blocksize; int skipfirst = 0; blknr = read_allocated_block(&(node->inode), i); - if (blknr < 0) { - len = -1; - goto out_exit; - } + if (blknr < 0) + return -1; blknr = blknr << log2_fs_blocksize; @@ -116,10 +106,8 @@ int ext4fs_read_file(struct ext2fs_node *node, int pos, delayed_skipfirst, delayed_extent, delayed_buf); - if (status == 0) { - len = -1; - goto out_exit; - } + if (status == 0) + return -1; previous_block_number = blknr; delayed_start = blknr; delayed_extent = blockend; @@ -144,10 +132,8 @@ int ext4fs_read_file(struct ext2fs_node *node, int pos, delayed_skipfirst, delayed_extent, delayed_buf); - if (status == 0) { - len = -1; - goto out_exit; - } + if (status == 0) + return -1; previous_block_number = -1; } memset(buf, 0, blocksize - skipfirst); @@ -159,17 +145,11 @@ int ext4fs_read_file(struct ext2fs_node *node, int pos, status = ext4fs_devread(delayed_start, delayed_skipfirst, delayed_extent, delayed_buf); - if (status == 0) { - len = -1; - goto out_exit; - } + if (status == 0) + return -1; previous_block_number = -1; } - -out_exit: - ext4fs_free_extent_cache(); - return len; }