Whamcloud - gitweb
b=11424
authorcliffw <cliffw>
Wed, 2 May 2007 18:37:00 +0000 (18:37 +0000)
committercliffw <cliffw>
Wed, 2 May 2007 18:37:00 +0000 (18:37 +0000)
r=scjody
rc=alex

Merge from LLNL chaos tree.

ldiskfs/kernel_patches/patches/ext3-extents-bug11324.patch [new file with mode: 0644]
ldiskfs/kernel_patches/series/ldiskfs-2.6-rhel4.series
lustre/kernel_patches/patches/ext3-extents-bug11324.patch [new file with mode: 0644]
lustre/kernel_patches/series/ldiskfs-2.6-rhel4.series

diff --git a/ldiskfs/kernel_patches/patches/ext3-extents-bug11324.patch b/ldiskfs/kernel_patches/patches/ext3-extents-bug11324.patch
new file mode 100644 (file)
index 0000000..c7ed475
--- /dev/null
@@ -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 <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);
index 27aed1d..ee07d11 100644 (file)
@@ -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 (file)
index 0000000..c7ed475
--- /dev/null
@@ -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 <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);
index 27aed1d..ee07d11 100644 (file)
@@ -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