diff options
-rw-r--r-- | fs/ext4/ext4_common.c | 164 | ||||
-rw-r--r-- | fs/ext4/ext4_common.h | 3 | ||||
-rw-r--r-- | fs/ext4/ext4fs.c | 36 |
3 files changed, 73 insertions, 130 deletions
diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c index 6584892..02da75c 100644 --- a/fs/ext4/ext4_common.c +++ b/fs/ext4/ext4_common.c @@ -26,7 +26,6 @@ #include <stddef.h> #include <linux/stat.h> #include <linux/time.h> -#include <linux/list.h> #include <asm/byteorder.h> #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 a9fd8c6..5fa1719 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 4f1b4c8..417ce7b 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; } |