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 6584892dd..02da75c08 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 a9fd8c657..5fa1719f2 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 4f1b4c8bc..417ce7b63 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;  } |