From 715b56fe2b47e073e6f2425e0cedba0e92a4014d Mon Sep 17 00:00:00 2001
From: Tom Rini <trini@ti.com>
Date: Wed, 26 Feb 2014 08:18:58 -0500
Subject: [PATCH] Revert "ext4fs: Add ext4 extent cache for read operations"
MIME-Version: 1.0
Content-Type: text/plain; charset=utf8
Content-Transfer-Encoding: 8bit

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 <l.majewski@samsung.com>
Signed-off-by: Tom Rini <trini@ti.com>
---
 fs/ext4/ext4_common.c | 164 +++++++++++++++++-------------------------
 fs/ext4/ext4_common.h |   3 -
 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 6584892dd2..02da75c084 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 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;
 }
 
-- 
2.39.5