--- /dev/null
+Index: linux-stage/fs/ext3/extents.c
+===================================================================
+--- linux-stage.orig/fs/ext3/extents.c 2007-04-17 22:09:19.000000000 -0700
++++ linux-stage/fs/ext3/extents.c 2007-04-17 22:12:05.000000000 -0700
+@@ -44,26 +44,49 @@
+ #include <asm/uaccess.h>
+
+
+-static inline int ext3_ext_check_header(struct ext3_extent_header *eh)
+-{
+- if (eh->eh_magic != EXT3_EXT_MAGIC) {
+- printk(KERN_ERR "EXT3-fs: invalid magic = 0x%x\n",
+- (unsigned)eh->eh_magic);
+- return -EIO;
+- }
+- if (eh->eh_max == 0) {
+- printk(KERN_ERR "EXT3-fs: invalid eh_max = %u\n",
+- (unsigned)eh->eh_max);
+- return -EIO;
+- }
+- if (eh->eh_entries > eh->eh_max) {
+- printk(KERN_ERR "EXT3-fs: invalid eh_entries = %u\n",
+- (unsigned)eh->eh_entries);
+- return -EIO;
++static int __ext3_ext_check_header(const char *function, struct inode *inode,
++ struct ext3_extent_header *eh, int depth,
++ int max)
++{
++ const char *error_msg = NULL;
++
++ if (unlikely(eh->eh_magic != EXT3_EXT_MAGIC)) {
++ error_msg = "invalid magic";
++ goto corrupted;
++ }
++ if (unlikely(eh->eh_depth != depth)) {
++ error_msg = "unexpected eh_depth";
++ goto corrupted;
++ }
++ if (unlikely(eh->eh_max == 0)) {
++ error_msg = "too small eh_max";
++ goto corrupted;
++ }
++ if (unlikely(eh->eh_max > max)) {
++ error_msg = "too large eh_max";
++ goto corrupted;
++ }
++ if (unlikely(eh->eh_entries > eh->eh_max)) {
++ error_msg = "invalid eh_entries";
++ goto corrupted;
+ }
+ return 0;
++
++corrupted:
++ ext3_error(inode->i_sb, function,
++ "bad header in inode #%lu: %s - magic %x, "
++ "entries %u, max %u(%u), depth %u(%u)",
++ inode->i_ino, error_msg, eh->eh_magic,
++ eh->eh_entries, eh->eh_max, max,
++ eh->eh_depth, depth);
++
++ return -EIO;
+ }
+
++#define ext3_ext_check_header(inode,eh,depth,max) \
++ __ext3_ext_check_header(__FUNCTION__,inode,eh,depth,max)
++
++
+ static handle_t *ext3_ext_journal_restart(handle_t *handle, int needed)
+ {
+ int err;
+@@ -226,6 +249,26 @@
+ return size;
+ }
+
++static inline int
++ext3_ext_max_entries(struct ext3_extents_tree *tree, int root, int depth)
++{
++ int max;
++
++ if (root) {
++ if (depth == 0)
++ max = ext3_ext_space_root(tree);
++ else
++ max = ext3_ext_space_root_idx(tree);
++ } else {
++ if (depth == 0)
++ max = ext3_ext_space_block(tree);
++ else
++ max = ext3_ext_space_block_idx(tree);
++ }
++
++ return max;
++}
++
+ static void ext3_ext_show_path(struct ext3_extents_tree *tree,
+ struct ext3_ext_path *path)
+ {
+@@ -296,10 +339,6 @@
+ struct ext3_extent_idx *ix;
+ int l = 0, k, r;
+
+- EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
+- EXT_ASSERT(eh->eh_entries <= eh->eh_max);
+- EXT_ASSERT(eh->eh_entries > 0);
+-
+ ext_debug(tree, "binsearch for %d(idx): ", block);
+
+ path->p_idx = ix = EXT_FIRST_INDEX(eh);
+@@ -359,9 +398,6 @@
+ struct ext3_extent *ex;
+ int l = 0, k, r;
+
+- EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
+- EXT_ASSERT(eh->eh_entries <= eh->eh_max);
+-
+ if (eh->eh_entries == 0) {
+ /*
+ * this leaf is empty yet:
+@@ -436,6 +472,7 @@
+ struct ext3_extent_header *eh;
+ struct buffer_head *bh;
+ int depth, i, ppos = 0;
++ int max;
+
+ EXT_ASSERT(tree);
+ EXT_ASSERT(tree->inode);
+@@ -443,17 +480,15 @@
+
+ eh = EXT_ROOT_HDR(tree);
+ EXT_ASSERT(eh);
+- if (ext3_ext_check_header(eh)) {
++ i = depth = EXT_DEPTH(tree);
++ max = ext3_ext_max_entries(tree, 1, i);
++ if (ext3_ext_check_header(tree->inode, eh, i, max)) {
+ /* don't free previously allocated path
+ * -- caller should take care */
+ path = NULL;
+ goto err;
+ }
+
+- i = depth = EXT_DEPTH(tree);
+- EXT_ASSERT(eh->eh_max);
+- EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
+-
+ /* account possible depth increase */
+ if (!path) {
+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2),
+@@ -484,8 +519,10 @@
+ path[ppos].p_hdr = eh;
+ i--;
+
+- if (ext3_ext_check_header(eh))
++ max = ext3_ext_max_entries(tree, 0, i);
++ if (ext3_ext_check_header(tree->inode, eh, i, max))
+ goto err;
++
+ }
+
+ path[ppos].p_depth = i;
+@@ -493,9 +530,6 @@
+ path[ppos].p_ext = NULL;
+ path[ppos].p_idx = NULL;
+
+- if (ext3_ext_check_header(eh))
+- goto err;
+-
+ /* find extent */
+ ext3_ext_binsearch(tree, path + ppos, block);
+
+@@ -1545,6 +1579,8 @@
+ ext_debug(tree, "remove [%lu:%lu] in leaf\n", start, end);
+ if (!path[depth].p_hdr)
+ path[depth].p_hdr = EXT_BLOCK_HDR(path[depth].p_bh);
++
++ /* the header must be checked already in ext3_ext_remove_space() */
+ eh = path[depth].p_hdr;
+ EXT_ASSERT(eh);
+ EXT_ASSERT(eh->eh_entries <= eh->eh_max);
+@@ -1707,7 +1743,7 @@
+ int depth = EXT_DEPTH(tree);
+ struct ext3_ext_path *path;
+ handle_t *handle;
+- int i = 0, err = 0;
++ int i = 0, err = 0, max;
+
+ ext_debug(tree, "space to be removed: %lu:%lu\n", start, end);
+
+@@ -1730,7 +1766,13 @@
+ }
+ memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1));
+ path[i].p_hdr = EXT_ROOT_HDR(tree);
+-
++
++ max = ext3_ext_max_entries(tree, 1, depth);
++ if (ext3_ext_check_header(inode, path[i].p_hdr, depth, max)) {
++ err = -EIO;
++ goto out;
++ }
++
+ while (i >= 0 && err == 0) {
+ if (i == depth) {
+ /* this is leaf block */
+@@ -1740,16 +1782,13 @@
+ i--;
+ continue;
+ }
+-
++
+ /* this is index block */
+ if (!path[i].p_hdr) {
+ ext_debug(tree, "initialize header\n");
+ path[i].p_hdr = EXT_BLOCK_HDR(path[i].p_bh);
+ }
+
+- EXT_ASSERT(path[i].p_hdr->eh_entries <= path[i].p_hdr->eh_max);
+- EXT_ASSERT(path[i].p_hdr->eh_magic == EXT3_EXT_MAGIC);
+-
+ if (!path[i].p_idx) {
+ /* this level hasn't touched yet */
+ path[i].p_idx =
+@@ -1776,6 +1815,14 @@
+ err = -EIO;
+ break;
+ }
++ BUG_ON(i + 1 > depth);
++ max = ext3_ext_max_entries(tree, 0, depth - i - 1);
++ if (ext3_ext_check_header(inode,
++ EXT_BLOCK_HDR(path[i+1].p_bh),
++ depth - i - 1, max)) {
++ err = -EIO;
++ break;
++ }
+ /* put actual number of indexes to know is this
+ * number got changed at the next iteration */
+ path[i].p_block = path[i].p_hdr->eh_entries;
+@@ -1796,7 +1843,7 @@
+ }
+
+ /* TODO: flexible tree reduction should be here */
+- if (path->p_hdr->eh_entries == 0) {
++ if (err == 0 && path->p_hdr->eh_entries == 0) {
+ /*
+ * truncate to zero freed all the tree
+ * so, we need to correct eh_depth
+@@ -1810,6 +1857,7 @@
+ }
+ ext3_ext_tree_changed(tree);
+
++out:
+ kfree(path);
+ ext3_journal_stop(handle);
+
ext3-sector_t-overflow-2.6.9-rhel4.patch
ext3-check-jbd-errors-2.6.9.patch
ext3-nanosecond-2.6-rhel4.patch
+ext3-extents-bug11324.patch
--- /dev/null
+Index: linux-stage/fs/ext3/extents.c
+===================================================================
+--- linux-stage.orig/fs/ext3/extents.c 2007-04-17 22:09:19.000000000 -0700
++++ linux-stage/fs/ext3/extents.c 2007-04-17 22:12:05.000000000 -0700
+@@ -44,26 +44,49 @@
+ #include <asm/uaccess.h>
+
+
+-static inline int ext3_ext_check_header(struct ext3_extent_header *eh)
+-{
+- if (eh->eh_magic != EXT3_EXT_MAGIC) {
+- printk(KERN_ERR "EXT3-fs: invalid magic = 0x%x\n",
+- (unsigned)eh->eh_magic);
+- return -EIO;
+- }
+- if (eh->eh_max == 0) {
+- printk(KERN_ERR "EXT3-fs: invalid eh_max = %u\n",
+- (unsigned)eh->eh_max);
+- return -EIO;
+- }
+- if (eh->eh_entries > eh->eh_max) {
+- printk(KERN_ERR "EXT3-fs: invalid eh_entries = %u\n",
+- (unsigned)eh->eh_entries);
+- return -EIO;
++static int __ext3_ext_check_header(const char *function, struct inode *inode,
++ struct ext3_extent_header *eh, int depth,
++ int max)
++{
++ const char *error_msg = NULL;
++
++ if (unlikely(eh->eh_magic != EXT3_EXT_MAGIC)) {
++ error_msg = "invalid magic";
++ goto corrupted;
++ }
++ if (unlikely(eh->eh_depth != depth)) {
++ error_msg = "unexpected eh_depth";
++ goto corrupted;
++ }
++ if (unlikely(eh->eh_max == 0)) {
++ error_msg = "too small eh_max";
++ goto corrupted;
++ }
++ if (unlikely(eh->eh_max > max)) {
++ error_msg = "too large eh_max";
++ goto corrupted;
++ }
++ if (unlikely(eh->eh_entries > eh->eh_max)) {
++ error_msg = "invalid eh_entries";
++ goto corrupted;
+ }
+ return 0;
++
++corrupted:
++ ext3_error(inode->i_sb, function,
++ "bad header in inode #%lu: %s - magic %x, "
++ "entries %u, max %u(%u), depth %u(%u)",
++ inode->i_ino, error_msg, eh->eh_magic,
++ eh->eh_entries, eh->eh_max, max,
++ eh->eh_depth, depth);
++
++ return -EIO;
+ }
+
++#define ext3_ext_check_header(inode,eh,depth,max) \
++ __ext3_ext_check_header(__FUNCTION__,inode,eh,depth,max)
++
++
+ static handle_t *ext3_ext_journal_restart(handle_t *handle, int needed)
+ {
+ int err;
+@@ -226,6 +249,26 @@
+ return size;
+ }
+
++static inline int
++ext3_ext_max_entries(struct ext3_extents_tree *tree, int root, int depth)
++{
++ int max;
++
++ if (root) {
++ if (depth == 0)
++ max = ext3_ext_space_root(tree);
++ else
++ max = ext3_ext_space_root_idx(tree);
++ } else {
++ if (depth == 0)
++ max = ext3_ext_space_block(tree);
++ else
++ max = ext3_ext_space_block_idx(tree);
++ }
++
++ return max;
++}
++
+ static void ext3_ext_show_path(struct ext3_extents_tree *tree,
+ struct ext3_ext_path *path)
+ {
+@@ -296,10 +339,6 @@
+ struct ext3_extent_idx *ix;
+ int l = 0, k, r;
+
+- EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
+- EXT_ASSERT(eh->eh_entries <= eh->eh_max);
+- EXT_ASSERT(eh->eh_entries > 0);
+-
+ ext_debug(tree, "binsearch for %d(idx): ", block);
+
+ path->p_idx = ix = EXT_FIRST_INDEX(eh);
+@@ -359,9 +398,6 @@
+ struct ext3_extent *ex;
+ int l = 0, k, r;
+
+- EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
+- EXT_ASSERT(eh->eh_entries <= eh->eh_max);
+-
+ if (eh->eh_entries == 0) {
+ /*
+ * this leaf is empty yet:
+@@ -436,6 +472,7 @@
+ struct ext3_extent_header *eh;
+ struct buffer_head *bh;
+ int depth, i, ppos = 0;
++ int max;
+
+ EXT_ASSERT(tree);
+ EXT_ASSERT(tree->inode);
+@@ -443,17 +480,15 @@
+
+ eh = EXT_ROOT_HDR(tree);
+ EXT_ASSERT(eh);
+- if (ext3_ext_check_header(eh)) {
++ i = depth = EXT_DEPTH(tree);
++ max = ext3_ext_max_entries(tree, 1, i);
++ if (ext3_ext_check_header(tree->inode, eh, i, max)) {
+ /* don't free previously allocated path
+ * -- caller should take care */
+ path = NULL;
+ goto err;
+ }
+
+- i = depth = EXT_DEPTH(tree);
+- EXT_ASSERT(eh->eh_max);
+- EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
+-
+ /* account possible depth increase */
+ if (!path) {
+ path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2),
+@@ -484,8 +519,10 @@
+ path[ppos].p_hdr = eh;
+ i--;
+
+- if (ext3_ext_check_header(eh))
++ max = ext3_ext_max_entries(tree, 0, i);
++ if (ext3_ext_check_header(tree->inode, eh, i, max))
+ goto err;
++
+ }
+
+ path[ppos].p_depth = i;
+@@ -493,9 +530,6 @@
+ path[ppos].p_ext = NULL;
+ path[ppos].p_idx = NULL;
+
+- if (ext3_ext_check_header(eh))
+- goto err;
+-
+ /* find extent */
+ ext3_ext_binsearch(tree, path + ppos, block);
+
+@@ -1545,6 +1579,8 @@
+ ext_debug(tree, "remove [%lu:%lu] in leaf\n", start, end);
+ if (!path[depth].p_hdr)
+ path[depth].p_hdr = EXT_BLOCK_HDR(path[depth].p_bh);
++
++ /* the header must be checked already in ext3_ext_remove_space() */
+ eh = path[depth].p_hdr;
+ EXT_ASSERT(eh);
+ EXT_ASSERT(eh->eh_entries <= eh->eh_max);
+@@ -1707,7 +1743,7 @@
+ int depth = EXT_DEPTH(tree);
+ struct ext3_ext_path *path;
+ handle_t *handle;
+- int i = 0, err = 0;
++ int i = 0, err = 0, max;
+
+ ext_debug(tree, "space to be removed: %lu:%lu\n", start, end);
+
+@@ -1730,7 +1766,13 @@
+ }
+ memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1));
+ path[i].p_hdr = EXT_ROOT_HDR(tree);
+-
++
++ max = ext3_ext_max_entries(tree, 1, depth);
++ if (ext3_ext_check_header(inode, path[i].p_hdr, depth, max)) {
++ err = -EIO;
++ goto out;
++ }
++
+ while (i >= 0 && err == 0) {
+ if (i == depth) {
+ /* this is leaf block */
+@@ -1740,16 +1782,13 @@
+ i--;
+ continue;
+ }
+-
++
+ /* this is index block */
+ if (!path[i].p_hdr) {
+ ext_debug(tree, "initialize header\n");
+ path[i].p_hdr = EXT_BLOCK_HDR(path[i].p_bh);
+ }
+
+- EXT_ASSERT(path[i].p_hdr->eh_entries <= path[i].p_hdr->eh_max);
+- EXT_ASSERT(path[i].p_hdr->eh_magic == EXT3_EXT_MAGIC);
+-
+ if (!path[i].p_idx) {
+ /* this level hasn't touched yet */
+ path[i].p_idx =
+@@ -1776,6 +1815,14 @@
+ err = -EIO;
+ break;
+ }
++ BUG_ON(i + 1 > depth);
++ max = ext3_ext_max_entries(tree, 0, depth - i - 1);
++ if (ext3_ext_check_header(inode,
++ EXT_BLOCK_HDR(path[i+1].p_bh),
++ depth - i - 1, max)) {
++ err = -EIO;
++ break;
++ }
+ /* put actual number of indexes to know is this
+ * number got changed at the next iteration */
+ path[i].p_block = path[i].p_hdr->eh_entries;
+@@ -1796,7 +1843,7 @@
+ }
+
+ /* TODO: flexible tree reduction should be here */
+- if (path->p_hdr->eh_entries == 0) {
++ if (err == 0 && path->p_hdr->eh_entries == 0) {
+ /*
+ * truncate to zero freed all the tree
+ * so, we need to correct eh_depth
+@@ -1810,6 +1857,7 @@
+ }
+ ext3_ext_tree_changed(tree);
+
++out:
+ kfree(path);
+ ext3_journal_stop(handle);
+
ext3-sector_t-overflow-2.6.9-rhel4.patch
ext3-check-jbd-errors-2.6.9.patch
ext3-nanosecond-2.6-rhel4.patch
+ext3-extents-bug11324.patch