From 5c2569bf5c14dac4cb64cd530afd6b0255c7e37b Mon Sep 17 00:00:00 2001 From: dzogin Date: Thu, 5 Nov 2009 22:10:32 +0000 Subject: [PATCH] Branch HEAD b=21031 i=andrew.perpechko i=girish.shilamkar ---------------------------------------------------------------------- Modified Files: ldiskfs/ChangeLog ldiskfs/kernel_patches/series/ldiskfs-2.6-rhel5.series ldiskfs/kernel_patches/series/ldiskfs-2.6-sles10.series Added Files: ldiskfs/kernel_patches/patches/ext3-corrupted-orphans-2.6.patch ---------------------------------------------------------------------- Description: ext3-corrupted-orphans-2.6.patch added. Details : Backport of ext3 patch to handle corrupted orphans. ------------------------------------------------------------------------------- --- ldiskfs/ChangeLog | 13 +- .../patches/ext3-corrupted-orphans-2.6.patch | 145 +++++++++++++++++++++ .../kernel_patches/series/ldiskfs-2.6-rhel5.series | 1 + .../series/ldiskfs-2.6-sles10.series | 1 + 4 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 ldiskfs/kernel_patches/patches/ext3-corrupted-orphans-2.6.patch diff --git a/ldiskfs/ChangeLog b/ldiskfs/ChangeLog index 5f13dca..d67c55c 100644 --- a/ldiskfs/ChangeLog +++ b/ldiskfs/ChangeLog @@ -1,9 +1,20 @@ tbd Sun Microsystems, Inc. - * version 3.1.0 + * version 3.1.1 ------------------------------------------------------------------------------- +2009-11-05 Sun Microsystems, Inc. + * version 3.1.0 + +Severity : normal +Frequency : in recovery +Bugzilla : 21031 +Description: ext3-corrupted-orphans-2.6.patch added. +Details : Backport of ext3 patch to handle corrupted orphans. + +------------------------------------------------------------------------------- + 2009-07-31 Sun Microsystems, Inc. * version 3.0.9 diff --git a/ldiskfs/kernel_patches/patches/ext3-corrupted-orphans-2.6.patch b/ldiskfs/kernel_patches/patches/ext3-corrupted-orphans-2.6.patch new file mode 100644 index 0000000..607cf1e --- /dev/null +++ b/ldiskfs/kernel_patches/patches/ext3-corrupted-orphans-2.6.patch @@ -0,0 +1,145 @@ +--- linux-2.6.18-128.7.1.orig/include/linux/ext3_fs.h 2006-09-19 23:42:06.000000000 -0400 ++++ linux-2.6.18-128.7.1/include/linux/ext3_fs.h 2009-10-12 19:37:54.000000000 -0400 +@@ -809,6 +809,7 @@ extern void ext3_discard_reservation (st + extern void ext3_dirty_inode(struct inode *); + extern int ext3_change_inode_journal_flag(struct inode *, int); + extern int ext3_get_inode_loc(struct inode *, struct ext3_iloc *); ++extern int ext3_can_truncate(struct inode *inode); + extern void ext3_truncate (struct inode *); + extern void ext3_set_inode_flags(struct inode *); + extern void ext3_set_aops(struct inode *inode); +--- linux-2.6.18-128.7.1.orig/fs/ext3/inode.c 2009-09-15 10:38:31.000000000 -0400 ++++ linux-2.6.18-128.7.1/fs/ext3/inode.c 2009-10-12 18:49:01.000000000 -0400 +@@ -2194,6 +2194,19 @@ static void ext3_free_branches(handle_t + } + } + ++int ext3_can_truncate(struct inode *inode) ++{ ++ if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) ++ return 0; ++ if (S_ISREG(inode->i_mode)) ++ return 1; ++ if (S_ISDIR(inode->i_mode)) ++ return 1; ++ if (S_ISLNK(inode->i_mode)) ++ return !ext3_inode_is_fast_symlink(inode); ++ return 0; ++} ++ + /* + * ext3_truncate() + * +@@ -2238,12 +2251,7 @@ void ext3_truncate(struct inode *inode) + unsigned blocksize = inode->i_sb->s_blocksize; + struct page *page; + +- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || +- S_ISLNK(inode->i_mode))) +- return; +- if (ext3_inode_is_fast_symlink(inode)) +- return; +- if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) ++ if (!ext3_can_truncate(inode)) + return; + + /* +--- linux-2.6.18-128.7.1.orig/fs/ext3/ialloc.c 2009-09-15 10:24:17.000000000 -0400 ++++ linux-2.6.18-128.7.1/fs/ext3/ialloc.c 2009-10-14 15:36:27.000000000 -0400 +@@ -645,54 +645,71 @@ struct inode *ext3_orphan_get(struct sup + unsigned long max_ino = le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count); + unsigned long block_group; + int bit; +- struct buffer_head *bitmap_bh = NULL; ++ struct buffer_head *bitmap_bh; + struct inode *inode = NULL; + + /* Error cases - e2fsck has already cleaned up for us */ + if (ino > max_ino) { +- ext3_warning(sb, __FUNCTION__, ++ ext3_warning(sb, __func__, + "bad orphan ino %lu! e2fsck was run?", ino); +- goto out; ++ goto error; + } + + block_group = (ino - 1) / EXT3_INODES_PER_GROUP(sb); + bit = (ino - 1) % EXT3_INODES_PER_GROUP(sb); + bitmap_bh = read_inode_bitmap(sb, block_group); + if (!bitmap_bh) { +- ext3_warning(sb, __FUNCTION__, ++ ext3_warning(sb, __func__, + "inode bitmap error for orphan %lu", ino); +- goto out; ++ goto error; + } + + /* Having the inode bit set should be a 100% indicator that this + * is a valid orphan (no e2fsck run on fs). Orphans also include + * inodes that were being truncated, so we can't check i_nlink==0. + */ +- if (!ext3_test_bit(bit, bitmap_bh->b_data) || +- !(inode = iget(sb, ino)) || is_bad_inode(inode) || +- NEXT_ORPHAN(inode) > max_ino) { +- ext3_warning(sb, __FUNCTION__, +- "bad orphan inode %lu! e2fsck was run?", ino); +- printk(KERN_NOTICE "ext3_test_bit(bit=%d, block=%llu) = %d\n", +- bit, (unsigned long long)bitmap_bh->b_blocknr, +- ext3_test_bit(bit, bitmap_bh->b_data)); +- printk(KERN_NOTICE "inode=%p\n", inode); +- if (inode) { +- printk(KERN_NOTICE "is_bad_inode(inode)=%d\n", +- is_bad_inode(inode)); +- printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n", +- NEXT_ORPHAN(inode)); +- printk(KERN_NOTICE "max_ino=%lu\n", max_ino); +- } ++ if (!ext3_test_bit(bit, bitmap_bh->b_data)) ++ goto bad_orphan; ++ ++ inode = iget(sb, ino); ++ if ((inode == NULL) || is_bad_inode(inode)) ++ goto bad_orphan; ++ ++ /* ++ * If the orphan has i_nlinks > 0 then it should be able to be ++ * truncated, otherwise it won't be removed from the orphan list ++ * during processing and an infinite loop will result. ++ */ ++ if (inode->i_nlink && !ext3_can_truncate(inode)) ++ goto bad_orphan; ++ ++ if (NEXT_ORPHAN(inode) > max_ino) ++ goto bad_orphan; ++ brelse(bitmap_bh); ++ return inode; ++ ++bad_orphan: ++ ext3_warning(sb, __func__, ++ "bad orphan inode %lu! e2fsck was run?", ino); ++ printk(KERN_NOTICE "ext3_test_bit(bit=%d, block=%llu) = %d\n", ++ bit, (unsigned long long)bitmap_bh->b_blocknr, ++ ext3_test_bit(bit, bitmap_bh->b_data)); ++ printk(KERN_NOTICE "inode=%p\n", inode); ++ if (inode) { ++ printk(KERN_NOTICE "is_bad_inode(inode)=%d\n", ++ is_bad_inode(inode)); ++ printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n", ++ NEXT_ORPHAN(inode)); ++ printk(KERN_NOTICE "max_ino=%lu\n", max_ino); ++ printk(KERN_NOTICE "i_nlink=%u\n", inode->i_nlink); + /* Avoid freeing blocks if we got a bad deleted inode */ +- if (inode && inode->i_nlink == 0) ++ if (inode->i_nlink == 0) + inode->i_blocks = 0; + iput(inode); +- inode = NULL; + } +-out: + brelse(bitmap_bh); +- return inode; ++error: ++ return NULL; + } + + unsigned long ext3_count_free_inodes (struct super_block * sb) diff --git a/ldiskfs/kernel_patches/series/ldiskfs-2.6-rhel5.series b/ldiskfs/kernel_patches/series/ldiskfs-2.6-rhel5.series index 8f87b9f..7f61ad5 100644 --- a/ldiskfs/kernel_patches/series/ldiskfs-2.6-rhel5.series +++ b/ldiskfs/kernel_patches/series/ldiskfs-2.6-rhel5.series @@ -33,5 +33,6 @@ ext3-osd-iam-exports.patch ext3-dynlocks-common.patch ext3-dynlocks-2.6-rhel5.patch ext3-hash-indexed-dir-dotdot-update.patch +ext3-corrupted-orphans-2.6.patch ext3-kill-dx_root.patch ext3_data_in_dirent.patch diff --git a/ldiskfs/kernel_patches/series/ldiskfs-2.6-sles10.series b/ldiskfs/kernel_patches/series/ldiskfs-2.6-sles10.series index 885df46..d9fc687 100644 --- a/ldiskfs/kernel_patches/series/ldiskfs-2.6-sles10.series +++ b/ldiskfs/kernel_patches/series/ldiskfs-2.6-sles10.series @@ -38,3 +38,4 @@ ext3-osd-iam-exports.patch ext3-dynlocks-common.patch ext3-dynlocks-2.6-rhel5.patch ext3-hash-indexed-dir-dotdot-update.patch +ext3-corrupted-orphans-2.6.patch -- 1.8.3.1