From 2a8110b14d2566b29402562cc6e9499b49af8363 Mon Sep 17 00:00:00 2001 From: cliffw Date: Wed, 2 May 2007 18:37:00 +0000 Subject: [PATCH] b=11424 r=scjody rc=alex Merge from LLNL chaos tree. --- .../patches/ext3-extents-bug11324.patch | 252 +++++++++++++++++++++ .../kernel_patches/series/ldiskfs-2.6-rhel4.series | 1 + .../patches/ext3-extents-bug11324.patch | 252 +++++++++++++++++++++ .../kernel_patches/series/ldiskfs-2.6-rhel4.series | 1 + 4 files changed, 506 insertions(+) create mode 100644 ldiskfs/kernel_patches/patches/ext3-extents-bug11324.patch create mode 100644 lustre/kernel_patches/patches/ext3-extents-bug11324.patch diff --git a/ldiskfs/kernel_patches/patches/ext3-extents-bug11324.patch b/ldiskfs/kernel_patches/patches/ext3-extents-bug11324.patch new file mode 100644 index 0000000..c7ed475 --- /dev/null +++ b/ldiskfs/kernel_patches/patches/ext3-extents-bug11324.patch @@ -0,0 +1,252 @@ +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 + + +-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); + diff --git a/ldiskfs/kernel_patches/series/ldiskfs-2.6-rhel4.series b/ldiskfs/kernel_patches/series/ldiskfs-2.6-rhel4.series index 27aed1d..ee07d11 100644 --- a/ldiskfs/kernel_patches/series/ldiskfs-2.6-rhel4.series +++ b/ldiskfs/kernel_patches/series/ldiskfs-2.6-rhel4.series @@ -14,3 +14,4 @@ ext3-lookup-dotdot-2.6.9.patch 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 diff --git a/lustre/kernel_patches/patches/ext3-extents-bug11324.patch b/lustre/kernel_patches/patches/ext3-extents-bug11324.patch new file mode 100644 index 0000000..c7ed475 --- /dev/null +++ b/lustre/kernel_patches/patches/ext3-extents-bug11324.patch @@ -0,0 +1,252 @@ +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 + + +-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); + diff --git a/lustre/kernel_patches/series/ldiskfs-2.6-rhel4.series b/lustre/kernel_patches/series/ldiskfs-2.6-rhel4.series index 27aed1d..ee07d11 100644 --- a/lustre/kernel_patches/series/ldiskfs-2.6-rhel4.series +++ b/lustre/kernel_patches/series/ldiskfs-2.6-rhel4.series @@ -14,3 +14,4 @@ ext3-lookup-dotdot-2.6.9.patch 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 -- 1.8.3.1